├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── changelog.md ├── etc └── spark-forge-deobf.jar ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── java └── mirror │ └── normalasm │ ├── NormalASM.java │ ├── NormalLogger.java │ ├── NormalPrinter.java │ ├── NormalReflector.java │ ├── UnsafeNormal.java │ ├── api │ ├── DeobfuscatingRewritePolicy.java │ ├── HashingStrategies.java │ ├── HasteUpload.java │ ├── ICapabilityDispatcherManipulator.java │ ├── IItemStackCapabilityDelayer.java │ ├── IItemStackCapabilityInjector.java │ ├── NormalStringPool.java │ ├── StacktraceDeobfuscator.java │ ├── datastructures │ │ ├── CaptureSet.java │ │ ├── DummyList.java │ │ ├── DummyMap.java │ │ ├── ImmutableArrayCollection.java │ │ ├── LazyChainedIterables.java │ │ ├── ResourceCache.java │ │ ├── canonical │ │ │ ├── AutoCanonizingArrayMap.java │ │ │ └── AutoCanonizingSet.java │ │ └── deobf │ │ │ ├── DeobfuscatedMappingsMap.java │ │ │ └── FieldDescriptionsMap.java │ └── mixins │ │ └── RegistrySimpleExtender.java │ ├── bakedquad │ ├── BakedQuadClassFactory.java │ ├── BakedQuadFactory.java │ ├── NormalVertexDataPool.java │ └── SupportingBakedQuad.java │ ├── client │ ├── NormalIncompatibilityHandler.java │ ├── mcfixes │ │ └── SkinDataReleaser.java │ ├── models │ │ ├── Deduplicator.java │ │ ├── MultipartBakedModelCache.java │ │ ├── bakedquad │ │ │ └── mixins │ │ │ │ └── HaxMixin.java │ │ ├── bucket │ │ │ ├── NormalBakedDynBucket.java │ │ │ └── mixins │ │ │ │ └── ModelDynBucketMixin.java │ │ ├── conditions │ │ │ └── CanonicalConditions.java │ │ ├── datastructures │ │ │ └── modelmanager │ │ │ │ └── mixins │ │ │ │ └── ModelManagerMixin.java │ │ └── mixins │ │ │ └── BlockFluidRendererMixin.java │ ├── rendering │ │ └── mixins │ │ │ └── VisGraphMixin.java │ ├── screenshot │ │ ├── ScreenshotListener.java │ │ ├── ScreenshotThread.java │ │ └── mixins │ │ │ ├── MinecraftMixin.java │ │ │ ├── ScreenShotHelperInvoker.java │ │ │ └── ScreenShotHelperMixin.java │ ├── searchtree │ │ ├── JEIRedirectSearchTree.java │ │ └── mixins │ │ │ ├── mod │ │ │ └── IngredientFilterInvoker.java │ │ │ └── vanilla │ │ │ └── MinecraftMixin.java │ └── sprite │ │ ├── FramesTextureData.java │ │ └── ondemand │ │ ├── FloorUV.java │ │ ├── FloorUVTree.java │ │ ├── IAnimatedSpriteActivator.java │ │ ├── IAnimatedSpritePrimer.java │ │ ├── IBufferPrimerConfigurator.java │ │ ├── ICompiledChunkExpander.java │ │ ├── IVertexLighterExpander.java │ │ └── mixins │ │ ├── BlockFluidRendererMixin.java │ │ ├── BlockModelRendererMixin.java │ │ ├── BufferBuilderMixin.java │ │ ├── ChunkCompileTaskGeneratorMixin.java │ │ ├── CompiledChunkMixin.java │ │ ├── ContainerLocalRenderInformationAccessor.java │ │ ├── ForgeBlockModelRendererMixin.java │ │ ├── ItemRendererMixin.java │ │ ├── RenderGlobalAccessor.java │ │ ├── RenderItemMixin.java │ │ ├── TextureAtlasSpriteMixin.java │ │ ├── TextureManagerMixin.java │ │ ├── TextureMapMixin.java │ │ └── VertexLighterFlatMixin.java │ ├── common │ ├── capability │ │ ├── astralsorcery │ │ │ └── mixins │ │ │ │ ├── AmuletHolderCapabilityProviderAccessor.java │ │ │ │ └── EnchantmentUpgradeHelperMixin.java │ │ └── mixins │ │ │ └── ItemStackMixin.java │ ├── crashes │ │ ├── CrashUtils.java │ │ ├── GuiCrashScreen.java │ │ ├── GuiInitErrorScreen.java │ │ ├── GuiProblemScreen.java │ │ ├── GuiWarningScreen.java │ │ ├── ICrashReportSuspectGetter.java │ │ ├── IMinecraftExtender.java │ │ ├── IStateful.java │ │ ├── ModIdentifier.java │ │ ├── ProblemToast.java │ │ └── mixins │ │ │ ├── BufferBuilderMixin.java │ │ │ ├── CrashReportCategoryMixin.java │ │ │ ├── CrashReportCategory_EntryInvoker.java │ │ │ ├── CrashReportMixin.java │ │ │ ├── EntityMixin.java │ │ │ ├── IntegratedServerMixin.java │ │ │ ├── MinecraftMixin.java │ │ │ ├── TileEntityMixin.java │ │ │ ├── TileEntityRenderDispatcherMixin.java │ │ │ └── UtilMixin.java │ ├── devenv │ │ └── mixins │ │ │ └── FMLModContainerMixin.java │ ├── efficienthashing │ │ └── mixins │ │ │ └── BlockPosMixin.java │ ├── forgefixes │ │ └── mixins │ │ │ ├── ChunkMixin.java │ │ │ ├── DimensionTypeMixin.java │ │ │ ├── EntityEntryMixin.java │ │ │ └── ForgeEventFactoryMixin.java │ ├── internal │ │ └── mixins │ │ │ ├── CapabilityDispatcherMixin.java │ │ │ ├── ItemStackMixin.java │ │ │ ├── LoadControllerMixin.java │ │ │ ├── TextureManagerAccessor.java │ │ │ └── TileEntityMixin.java │ ├── java │ │ └── JavaFixes.java │ ├── lockcode │ │ └── mixins │ │ │ └── LockCodeMixin.java │ ├── mcfixes │ │ └── mixins │ │ │ ├── mc129057 │ │ │ └── InventoryPlayerMixin.java │ │ │ ├── mc129556 │ │ │ └── MinecraftMixin.java │ │ │ ├── mc2071 │ │ │ └── EntityPlayerSPMixin.java │ │ │ └── skindownloading │ │ │ └── ThreadDownloadImageDataMixin.java │ ├── misc_fluidregistry │ │ └── mixins │ │ │ └── FluidRegistryMixin.java │ ├── modfixes │ │ ├── astralsorcery │ │ │ └── mixins │ │ │ │ ├── EnchantmentUpgradeHelperInvoker.java │ │ │ │ ├── ItemEnchantmentAmuletMixin.java │ │ │ │ └── PlayerAmuletHandlerMixin.java │ │ ├── b3m │ │ │ ├── CapitalizedNamespaceResourceLocation.java │ │ │ └── mixins │ │ │ │ └── B3M_CoreMixin.java │ │ ├── betterwithmods │ │ │ └── BWMBlastingOilOptimization.java │ │ ├── ebwizardry │ │ │ ├── ArcaneLocks.java │ │ │ └── mixins │ │ │ │ └── RenderArcaneLockMixin.java │ │ ├── evilcraftcompat │ │ │ └── mixins │ │ │ │ └── EnderIORecipeManagerMixin.java │ │ ├── immersiveengineering │ │ │ └── mixins │ │ │ │ └── BlockIEBaseMixin.java │ │ ├── qmd │ │ │ └── QMDEventHandler.java │ │ └── xu2 │ │ │ ├── TileCrafterExtension.java │ │ │ └── mixins │ │ │ ├── TileCrafterMixin.java │ │ │ └── XUTESRBaseMixin.java │ ├── recipes │ │ └── mixins │ │ │ └── FurnaceRecipesMixin.java │ ├── registries │ │ └── mixins │ │ │ ├── RegistrySimpleMixin.java │ │ │ └── SoundRegistryMixin.java │ ├── singletonevents │ │ ├── IRefreshEvent.java │ │ └── mixins │ │ │ ├── FMLCommonHandlerMixin.java │ │ │ ├── ForgeEventFactoryMixin.java │ │ │ ├── blocks │ │ │ ├── BlockEventMixin.java │ │ │ └── NeighborNotifyEventMixin.java │ │ │ ├── capabilities │ │ │ └── AttachCapabilitiesEventMixin.java │ │ │ └── gameevent │ │ │ ├── PlayerTickEventMixin.java │ │ │ ├── RenderTickEventMixin.java │ │ │ ├── TickEventMixin.java │ │ │ └── WorldTickEventMixin.java │ ├── stripitemstack │ │ └── mixins │ │ │ └── ItemStackMixin.java │ └── vanities │ │ └── mixins │ │ └── FMLCommonHandlerMixin.java │ ├── config │ ├── NormalConfig.java │ └── annotation │ │ ├── Ignore.java │ │ └── Since.java │ ├── core │ ├── NormalFMLCallHook.java │ ├── NormalHooks.java │ ├── NormalLateMixinLoader.java │ ├── NormalLoadingPlugin.java │ ├── NormalMixinPlugin.java │ ├── NormalTransformer.java │ └── classfactories │ │ └── BakedQuadRedirectorFactory.java │ ├── patches │ ├── BakedQuadFactoryPatch.java │ ├── BakedQuadPatch.java │ ├── BakedQuadRetexturedPatch.java │ ├── RenderGlobalPatch.java │ └── UnpackedBakedQuadPatch.java │ ├── proxy │ ├── ClientProxy.java │ └── CommonProxy.java │ ├── spark │ └── NormalSparker.java │ └── vanillafix │ └── bugfixes │ └── mixins │ ├── MixinBlockStateContainer.java │ ├── MixinEntity.java │ ├── MixinEntityPlayerMP.java │ ├── MixinEntityTrackerEntry.java │ └── client │ └── MixinIntegratedServer.java └── resources ├── META-INF └── normalasm_at.cfg ├── assets └── normalasm │ ├── lang │ ├── de_de.lang │ ├── en_us.lang │ ├── fr_fr.lang │ ├── pt_br.lang │ ├── ro_ro.lang │ ├── ru_ru.lang │ └── zh_cn.lang │ └── normalasm.png ├── mcmod.info ├── mixins.bakedquadsquasher.json ├── mixins.bucket.json ├── mixins.capability.json ├── mixins.capability_astralsorcery.json ├── mixins.crashes.json ├── mixins.datastructures_modelmanager.json ├── mixins.devenv.json ├── mixins.efficienthashing.json ├── mixins.fix_mc129057.json ├── mixins.fix_mc129556.json ├── mixins.fix_mc_skindownloading.json ├── mixins.forgefixes.json ├── mixins.internal.json ├── mixins.lockcode.json ├── mixins.misc_fluidregistry.json ├── mixins.modfixes_astralsorcery.json ├── mixins.modfixes_b3m.json ├── mixins.modfixes_ebwizardry.json ├── mixins.modfixes_evilcraftcompat.json ├── mixins.modfixes_immersiveengineering.json ├── mixins.modfixes_xu2.json ├── mixins.ondemand_sprites.json ├── mixins.recipes.json ├── mixins.registries.json ├── mixins.rendering.json ├── mixins.resolve_mc2071.json ├── mixins.screenshot.json ├── mixins.searchtree_mod.json ├── mixins.searchtree_vanilla.json ├── mixins.singletonevents.json ├── mixins.stripitemstack.json ├── mixins.vanities.json ├── mixins.vfix_bugfixes.json └── pack.mcmeta /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # gradle 17 | build 18 | .gradle 19 | 20 | # other 21 | eclipse 22 | run 23 | 24 | libs/spark-forge-deobf.jar 25 | 26 | logs/ 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NormalASM 2 | NormalASM is now preparing to bytecode manipulate your game. 3 | 4 | This is a fork of [LoliASM](https://github.com/LoliKingdom/LoliASM), for those who would prefer to not see pedophilic content in their game. 5 | This fork does not and will not change any aspects of `LoliASM` besides branding and will stay as up-to-date with upstream as possible. 6 | 7 | Any issue reports or pull requests (unrelated to branding changes) should be sent upstream. 8 | -------------------------------------------------------------------------------- /etc/spark-forge-deobf.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirrorcult/NormalASM/d3e8bddc7a81a662feb19acb7ebf8d008e237600/etc/spark-forge-deobf.jar -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx3G 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirrorcult/NormalASM/d3e8bddc7a81a662feb19acb7ebf8d008e237600/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 14 12:28:28 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/NormalASM.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm; 2 | 3 | import codechicken.asm.ClassHierarchyManager; 4 | import mirror.normalasm.core.NormalLoadingPlugin; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import net.minecraft.tileentity.TileEntity; 7 | import net.minecraftforge.fml.common.Mod; 8 | import net.minecraftforge.fml.common.SidedProxy; 9 | import net.minecraftforge.fml.common.event.*; 10 | import mirror.normalasm.api.mixins.RegistrySimpleExtender; 11 | import mirror.normalasm.config.NormalConfig; 12 | import mirror.normalasm.proxy.CommonProxy; 13 | 14 | import java.util.*; 15 | import java.util.function.BiConsumer; 16 | 17 | @Mod(modid = "normalasm", name = "NormalASM", version = NormalLoadingPlugin.VERSION, dependencies = "required-after:mixinbooter@[4.2,);after:jei;after:spark@[1.5.2]") 18 | public class NormalASM { 19 | 20 | @SidedProxy(modId = "normalasm", clientSide = "mirror.normalasm.proxy.ClientProxy", serverSide = "mirror.normalasm.proxy.CommonProxy") 21 | public static CommonProxy proxy; 22 | 23 | public static List simpleRegistryInstances = new ArrayList<>(); 24 | 25 | public static BiConsumer customTileDataConsumer; 26 | 27 | static { 28 | if (NormalConfig.instance.cleanupChickenASMClassHierarchyManager && NormalReflector.doesClassExist("codechicken.asm.ClassHierarchyManager")) { 29 | // EXPERIMENTAL: As far as I know, this functionality of ChickenASM isn't actually used by any coremods that depends on ChickenASM 30 | NormalLogger.instance.info("Replacing ClassHierarchyManager::superclasses with a dummy map."); 31 | ClassHierarchyManager.superclasses = new HashMap() { 32 | @Override 33 | public Object put(Object key, Object value) { 34 | return value; 35 | } 36 | }; 37 | } 38 | } 39 | 40 | @Mod.EventHandler 41 | public void construct(FMLConstructionEvent event) { 42 | proxy.construct(event); 43 | } 44 | 45 | @Mod.EventHandler 46 | public void preInit(FMLPreInitializationEvent event) { 47 | proxy.throwIncompatibility(); 48 | proxy.preInit(event); 49 | } 50 | 51 | @Mod.EventHandler 52 | public void init(FMLInitializationEvent event) { 53 | proxy.init(event); 54 | } 55 | 56 | @Mod.EventHandler 57 | public void postInit(FMLPostInitializationEvent event) { 58 | proxy.postInit(event); 59 | } 60 | 61 | @Mod.EventHandler 62 | public void loadComplete(FMLLoadCompleteEvent event) { 63 | proxy.loadComplete(event); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/NormalLogger.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | public class NormalLogger { 7 | 8 | public static final Logger instance = LogManager.getLogger("NormalASM"); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/NormalPrinter.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm; 2 | 3 | import javax.annotation.Nullable; 4 | import java.io.*; 5 | 6 | public class NormalPrinter { 7 | 8 | public static void prettyPrintClass(byte[] bytes, @Nullable File fileLocation) { 9 | FileOutputStream stream = null; 10 | if (fileLocation != null) { 11 | try { 12 | stream = new FileOutputStream(fileLocation); 13 | } catch (FileNotFoundException e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | if (stream == null) { 18 | stream = new FileOutputStream(FileDescriptor.out); 19 | } 20 | try { 21 | stream.write(bytes); 22 | stream.flush(); 23 | } catch (IOException e) { 24 | e.printStackTrace(); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/UnsafeNormal.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm; 2 | 3 | import io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess; 4 | import sun.misc.Unsafe; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | public class UnsafeNormal { 9 | 10 | private static final Unsafe $ = UnsafeAccess.UNSAFE; 11 | 12 | public static void removeFMLSecurityManager() { 13 | NormalLogger.instance.warn("Detaching FMLSecurityManager."); 14 | Field out = NormalReflector.getField(System.class, "out"); 15 | Field err = NormalReflector.getField(System.class, "err"); 16 | long errOffset = $.staticFieldOffset(err); 17 | long offset = errOffset + (errOffset - $.staticFieldOffset(out)); 18 | $.putObjectVolatile($.staticFieldBase(err), offset, null); 19 | if (System.getSecurityManager() != null) { 20 | NormalLogger.instance.warn("Failed to detach FMLSecurityManager."); 21 | } 22 | } 23 | 24 | private UnsafeNormal() { } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/DeobfuscatingRewritePolicy.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.core.LogEvent; 5 | import org.apache.logging.log4j.core.Logger; 6 | import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender; 7 | import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy; 8 | import org.apache.logging.log4j.core.config.AppenderRef; 9 | import org.apache.logging.log4j.core.config.LoggerConfig; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class DeobfuscatingRewritePolicy implements RewritePolicy { 15 | 16 | /** Modifies the log4j config to add the policy **/ 17 | public static void install() { 18 | Logger rootLogger = (Logger) LogManager.getRootLogger(); 19 | LoggerConfig loggerConfig = rootLogger.get(); 20 | // Remove appender refs from config 21 | List appenderRefs = new ArrayList<>(loggerConfig.getAppenderRefs()); 22 | for (AppenderRef appenderRef : appenderRefs) { 23 | loggerConfig.removeAppender(appenderRef.getRef()); 24 | } 25 | // Create the RewriteAppender, which wraps the appenders 26 | RewriteAppender rewriteAppender = RewriteAppender.createAppender( 27 | "NormalDeobfuscatingAppender", 28 | "true", 29 | appenderRefs.toArray(new AppenderRef[0]), 30 | rootLogger.getContext().getConfiguration(), 31 | new DeobfuscatingRewritePolicy(), 32 | null 33 | ); 34 | rewriteAppender.start(); 35 | // Add the new appender 36 | loggerConfig.addAppender(rewriteAppender, null, null); 37 | } 38 | 39 | @Override 40 | public LogEvent rewrite(LogEvent source) { 41 | if (source.getThrown() != null) { 42 | StacktraceDeobfuscator.deobfuscateThrowable(source.getThrown()); 43 | } 44 | return source; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/HasteUpload.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonObject; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | import java.nio.charset.StandardCharsets; 13 | 14 | public final class HasteUpload { 15 | 16 | public static String uploadToHaste(String str) throws IOException { 17 | str = "content=" + str; 18 | byte[] bytes = str.getBytes(StandardCharsets.UTF_8); 19 | URL uploadURL = new URL("https://api.mclo.gs/1/log"); 20 | HttpURLConnection connection = (HttpURLConnection) uploadURL.openConnection(); 21 | connection.setRequestMethod("POST"); 22 | connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); 23 | connection.setRequestProperty("User-Agent", "NormalASM"); 24 | connection.setFixedLengthStreamingMode(bytes.length); 25 | connection.setDoInput(true); 26 | connection.setDoOutput(true); 27 | connection.connect(); 28 | try { 29 | try (OutputStream os = connection.getOutputStream()) { 30 | os.write(bytes); 31 | } 32 | try (InputStream is = connection.getInputStream()) { 33 | JsonObject json = new Gson().fromJson(new InputStreamReader(is), JsonObject.class); 34 | return json.get("url").getAsString(); 35 | } 36 | } finally { 37 | connection.disconnect(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/ICapabilityDispatcherManipulator.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api; 2 | 3 | import net.minecraft.util.EnumFacing; 4 | import net.minecraft.util.ResourceLocation; 5 | import net.minecraftforge.common.capabilities.Capability; 6 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 7 | 8 | import javax.annotation.Nullable; 9 | 10 | /** 11 | * {@link net.minecraftforge.common.capabilities.CapabilityDispatcher} implements this at runtime. 12 | * 13 | * This interface allows internal manipulation of capabilities, mainly injection and stripping of capabilities. 14 | */ 15 | public interface ICapabilityDispatcherManipulator { 16 | 17 | void injectCapability(String name, ICapabilityProvider provider); 18 | 19 | default void injectCapability(ResourceLocation name, ICapabilityProvider provider) { 20 | injectCapability(name.toString(), provider); 21 | } 22 | 23 | void stripCapability(String name, Capability capability, @Nullable EnumFacing facing, T capabilityInstance); 24 | 25 | default void stripCapability(ResourceLocation name, Capability capability, @Nullable EnumFacing facing, T capabilityInstance) { 26 | stripCapability(name.toString(), capability, facing, capabilityInstance); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/IItemStackCapabilityDelayer.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api; 2 | 3 | import mirror.normalasm.config.NormalConfig; 4 | 5 | /** 6 | * {@link net.minecraft.item.ItemStack} implements this at runtime. 7 | * 8 | * This interface aids the delaying of capabilities initialization if {@link NormalConfig#delayItemStackCapabilityInit} == true 9 | */ 10 | public interface IItemStackCapabilityDelayer { 11 | 12 | boolean hasInitializedCapabilities(); 13 | 14 | /** 15 | * Can only run when {@link IItemStackCapabilityDelayer#hasInitializedCapabilities()} == true 16 | */ 17 | void initializeCapabilities(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/IItemStackCapabilityInjector.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | import net.minecraftforge.common.capabilities.CapabilityDispatcher; 5 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 6 | 7 | /** 8 | * {@link net.minecraft.item.ItemStack} implements this at runtime. 9 | * 10 | * This interface aids the initialization of capabilities in an on-demand manner. 11 | */ 12 | public interface IItemStackCapabilityInjector { 13 | 14 | CapabilityDispatcher getDispatcher(); 15 | 16 | CapabilityDispatcher initDispatcher(ResourceLocation capabilityKey, ICapabilityProvider provider); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/CaptureSet.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | public class CaptureSet extends HashSet { 9 | 10 | private final Set backingCaptures; 11 | 12 | public CaptureSet() { 13 | super(); 14 | this.backingCaptures = new ObjectOpenHashSet<>(); 15 | } 16 | 17 | public CaptureSet(Set populate) { 18 | this(); 19 | addAll(populate); 20 | } 21 | 22 | public void addCapture(K capture) { 23 | this.backingCaptures.add(capture); 24 | } 25 | 26 | public boolean put(K k) { 27 | return super.add(k); 28 | } 29 | 30 | @Override 31 | public boolean add(K k) { 32 | return this.backingCaptures.contains(k) || super.add(k); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/DummyList.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectIterators; 4 | 5 | import java.util.*; 6 | 7 | public class DummyList implements List { 8 | 9 | private static final DummyList INSTANCE = new DummyList<>(); 10 | 11 | @SuppressWarnings("unchecked") 12 | public static List of() { 13 | return (DummyList) INSTANCE; 14 | } 15 | 16 | @Override 17 | public int size() { return 0; } 18 | 19 | @Override 20 | public boolean isEmpty() { return true; } 21 | 22 | @Override 23 | public boolean contains(Object o) { return false; } 24 | 25 | @Override 26 | public Iterator iterator() { return Collections.emptyIterator(); } 27 | 28 | @Override 29 | public Object[] toArray() { return new Object[0]; } 30 | 31 | @Override 32 | public T[] toArray(T[] a) { return (T[]) new Object[0]; } 33 | 34 | @Override 35 | public boolean add(K k) { return false; } 36 | 37 | @Override 38 | public boolean remove(Object o) { return false; } 39 | 40 | @Override 41 | public boolean containsAll(Collection c) { return false; } 42 | 43 | @Override 44 | public boolean addAll(Collection c) { return false; } 45 | 46 | @Override 47 | public boolean addAll(int index, Collection c) { return false; } 48 | 49 | @Override 50 | public boolean removeAll(Collection c) { return false; } 51 | 52 | @Override 53 | public boolean retainAll(Collection c) { return false; } 54 | 55 | @Override 56 | public void clear() { } 57 | 58 | @Override 59 | public K get(int index) { return null; } 60 | 61 | @Override 62 | public K set(int index, K element) { return null; } 63 | 64 | @Override 65 | public void add(int index, K element) { } 66 | 67 | @Override 68 | public K remove(int index) { return null; } 69 | 70 | @Override 71 | public int indexOf(Object o) { return -1; } 72 | 73 | @Override 74 | public int lastIndexOf(Object o) { return -1; } 75 | 76 | @Override 77 | public ListIterator listIterator() { return ObjectIterators.EMPTY_ITERATOR; } 78 | 79 | @Override 80 | public ListIterator listIterator(int index) { return ObjectIterators.EMPTY_ITERATOR; } 81 | 82 | @Override 83 | public List subList(int fromIndex, int toIndex) { return DummyList.of(); } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/DummyMap.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * Used as a ImmutableMap-like structure, but with the methods not throwing UnsupportedOperationException 10 | */ 11 | public class DummyMap implements Map { 12 | 13 | private static final DummyMap INSTANCE = new DummyMap<>(); 14 | private static final Set SET_INSTANCE = Collections.newSetFromMap(INSTANCE); 15 | 16 | @SuppressWarnings("unchecked") 17 | public static Map of() { 18 | return (DummyMap) INSTANCE; 19 | } 20 | 21 | @SuppressWarnings("unchecked") 22 | public static Set asSet() { 23 | return (Set) SET_INSTANCE; 24 | } 25 | 26 | public int size() { return 0; } 27 | 28 | public boolean isEmpty() { return true; } 29 | 30 | public boolean containsKey(Object key) { return false; } 31 | 32 | public boolean containsValue(Object value) { return false; } 33 | 34 | public V get(Object key) { return null; } 35 | 36 | public V put(K key, V value) { return value; } 37 | 38 | public V remove(Object key) { return null; } 39 | 40 | public void putAll(Map m) { } 41 | 42 | public void clear() { } 43 | 44 | public Set keySet() { return Collections.emptySet(); } 45 | 46 | public Collection values() { return Collections.emptySet(); } 47 | 48 | public Set entrySet() { return Collections.emptySet(); } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/LazyChainedIterables.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures; 2 | 3 | import java.util.Iterator; 4 | import java.util.function.Supplier; 5 | 6 | public class LazyChainedIterables implements Iterable { 7 | 8 | private final Supplier>[] iterables; 9 | 10 | @SafeVarargs 11 | public LazyChainedIterables(Supplier>... iterables) { 12 | this.iterables = iterables; 13 | } 14 | 15 | @Override 16 | public Iterator iterator() { 17 | return new Iterator() { 18 | int index = 0; 19 | Iterator currentIterator = iterables[index].get().iterator(); 20 | @Override 21 | public boolean hasNext() { 22 | if (!currentIterator.hasNext()) { 23 | if (++index == iterables.length) { 24 | return false; 25 | } 26 | currentIterator = iterables[index].get().iterator(); 27 | } 28 | return true; 29 | } 30 | @Override 31 | public T next() { 32 | return currentIterator.next(); 33 | } 34 | }; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/ResourceCache.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 4 | 5 | public class ResourceCache extends Object2ObjectOpenHashMap { 6 | 7 | public byte[] add(String s, byte[] bytes) { 8 | return super.put(s, bytes); 9 | } 10 | 11 | @Override 12 | public byte[] put(String s, byte[] bytes) { 13 | return bytes; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/canonical/AutoCanonizingArrayMap.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures.canonical; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; 4 | import mirror.normalasm.api.NormalStringPool; 5 | 6 | import java.util.Map; 7 | 8 | public class AutoCanonizingArrayMap extends Object2ObjectArrayMap { 9 | 10 | public AutoCanonizingArrayMap() { 11 | super(); 12 | } 13 | 14 | public AutoCanonizingArrayMap(Map map) { 15 | super(map); 16 | } 17 | 18 | @Override 19 | public V put(K k, V v) { 20 | if (k instanceof String) { 21 | k = (K) NormalStringPool.canonicalize((String) k); 22 | } 23 | if (v instanceof String) { 24 | v = (V) NormalStringPool.canonicalize((String) v); 25 | } 26 | return super.put(k, v); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/canonical/AutoCanonizingSet.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures.canonical; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 4 | import mirror.normalasm.api.NormalStringPool; 5 | 6 | import java.util.Set; 7 | 8 | // TODO: Hook Deduplicator's pools 9 | public class AutoCanonizingSet extends ObjectOpenHashSet { 10 | 11 | public AutoCanonizingSet(Set set) { 12 | super(set); 13 | } 14 | 15 | @Override 16 | public boolean add(K k) { 17 | if (k instanceof String) { 18 | k = (K) NormalStringPool.canonicalize((String) k); 19 | } 20 | return super.add(k); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/deobf/DeobfuscatedMappingsMap.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures.deobf; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 4 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 5 | import mirror.normalasm.api.datastructures.DummyMap; 6 | import mirror.normalasm.api.datastructures.canonical.AutoCanonizingArrayMap; 7 | import mirror.normalasm.api.NormalStringPool; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * This is a special Map structure that replaces the raw and cached mappings. 13 | * 14 | * - Anything class that is a Minecraft or MinecraftForge class passes the check and is placed in the map 15 | * - Anything that has its inner maps containing String values that matches any SRG mapping is placed in the map 16 | */ 17 | public class DeobfuscatedMappingsMap extends Object2ObjectOpenHashMap> { 18 | 19 | // TODO: Move to deduplicator 20 | private static final ObjectOpenHashSet> innerMapCanonicalCache = new ObjectOpenHashSet<>(); 21 | 22 | // Typed as this for the MethodHandle 23 | public static Map> of(Map> startingMap, boolean isField) { 24 | return new DeobfuscatedMappingsMap(startingMap, isField); 25 | } 26 | 27 | private final String prefix; 28 | 29 | DeobfuscatedMappingsMap(Map> startingMap, boolean isField) { 30 | super(startingMap); 31 | this.prefix = isField ? "field_" : "func_"; 32 | } 33 | 34 | @Override 35 | public Map put(String s, Map innerMap) { 36 | if (s.indexOf('/') == -1 || s.startsWith("net/minecraft")) { // If it is a Minecraft or MinecraftForge class, we add to the map (short circuiting operation to not check innerMap strings) 37 | return super.put(NormalStringPool.canonicalize(s), innerMapCanonicalCache.addOrGet(new AutoCanonizingArrayMap<>(innerMap))); 38 | } else if (innerMap.isEmpty()) { // If there are no methods or fields mapped to 's' class, we return null and add nothing in the map 39 | return innerMap; 40 | } else if (innerMap.values().stream().anyMatch(string -> string.startsWith(prefix))) { 41 | return super.put(NormalStringPool.canonicalize(s), innerMapCanonicalCache.addOrGet(new AutoCanonizingArrayMap<>(innerMap))); // Check if any of the values start with 'func_' or 'field_', indicating that these 99% are mappings 42 | } 43 | /* 44 | for (Map.Entry entry : innerMap.entrySet()) { 45 | // Check if any of the values start with 'func_' or 'field_', indicating that these 99% are mappings 46 | if (Stream.of("func_", "field_").anyMatch(entry.getValue()::startsWith)) { 47 | return super.put(s, innerMap); 48 | } 49 | } 50 | */ 51 | // If all of this fails, return innerMap. 52 | return innerMap; 53 | } 54 | 55 | @Override 56 | public Map get(Object k) { 57 | Map get = super.get(k); 58 | return get == null ? DummyMap.of() : get; // Return DummyMap instead of Collections.emptyMap to not throw UnsupportedOperationException when Map#put 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/datastructures/deobf/FieldDescriptionsMap.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.datastructures.deobf; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; 4 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 5 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 6 | import mirror.normalasm.api.datastructures.canonical.AutoCanonizingArrayMap; 7 | import mirror.normalasm.api.NormalStringPool; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * This replaces the fieldDescriptions map in the remapper, it canonicalizes the inner maps and the inner maps' strings 13 | */ 14 | public class FieldDescriptionsMap extends Object2ObjectOpenHashMap> { 15 | 16 | // TODO: Move to deduplicator 17 | private static final ObjectOpenHashSet> innerMapCanonicalCache = new ObjectOpenHashSet<>(); 18 | 19 | public FieldDescriptionsMap(Map> startingMap) { 20 | super(startingMap); 21 | } 22 | 23 | @Override 24 | public Map put(String s, Map innerMap) { 25 | s = NormalStringPool.canonicalize(s); 26 | if (!(innerMap instanceof Object2ObjectArrayMap)) { 27 | innerMap = innerMapCanonicalCache.addOrGet(new AutoCanonizingArrayMap<>(innerMap)); 28 | } 29 | return super.put(s, innerMap); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/api/mixins/RegistrySimpleExtender.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.api.mixins; 2 | 3 | public interface RegistrySimpleExtender { 4 | 5 | void clearUnderlyingMap(); 6 | 7 | void trim(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/bakedquad/BakedQuadFactory.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.bakedquad; 2 | 3 | import mirror.normalasm.core.NormalTransformer; 4 | import net.minecraft.client.renderer.block.model.BakedQuad; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import net.minecraft.client.renderer.vertex.VertexFormat; 7 | import net.minecraft.util.EnumFacing; 8 | 9 | /** 10 | * This class aids the dispatches of BakedQuad instances. The create method is removed/patched in {@link NormalTransformer} 11 | */ 12 | @SuppressWarnings("unused") 13 | public final class BakedQuadFactory { 14 | 15 | // This is to avoid creating a synthetic EnumFacing SwitchMap at compile time 16 | // The SwitchMap is literally just an int array or enum ordinal positions 17 | private static final int[] pseudoSwitchMap = new int[] { 0, 1, 2, 3, 4, 5 }; 18 | 19 | public static BakedQuad canonicalize(int[] vertexData, int tintIndex, EnumFacing face, TextureAtlasSprite sprite, boolean applyDiffuseLighting, VertexFormat format) { 20 | return prepare(NormalVertexDataPool.canonicalize(vertexData), tintIndex, face, sprite, applyDiffuseLighting, format); 21 | } 22 | 23 | public static BakedQuad prepare(int[] vertexData, int tintIndex, EnumFacing face, TextureAtlasSprite sprite, boolean applyDiffuseLighting, VertexFormat format) { 24 | if (face == null) { 25 | // AE2 AutoRotatingModel applies null faces in certain contexts, not going to optimize these 26 | return new BakedQuad(vertexData, tintIndex, face, sprite, applyDiffuseLighting, format); 27 | } 28 | return create(vertexData, tintIndex, face, sprite, applyDiffuseLighting, format); 29 | } 30 | 31 | /** 32 | * This method is here as a placeholder. The contents of this method has to be dynamically written at runtime. 33 | */ 34 | public static BakedQuad create(int[] vertexData, int tintIndex, EnumFacing face, TextureAtlasSprite sprite, boolean applyDiffuseLighting, VertexFormat format) { 35 | return new BakedQuad(vertexData, tintIndex, face, sprite, applyDiffuseLighting, format); 36 | } 37 | 38 | private BakedQuadFactory() { } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/bakedquad/NormalVertexDataPool.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.bakedquad; 2 | 3 | import it.unimi.dsi.fastutil.ints.IntArrays; 4 | import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.renderer.block.model.BakedQuad; 7 | import net.minecraft.util.text.TextFormatting; 8 | import net.minecraftforge.client.event.RenderGameOverlayEvent; 9 | import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; 10 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 11 | import mirror.normalasm.NormalLogger; 12 | 13 | import java.util.ArrayList; 14 | 15 | public class NormalVertexDataPool { 16 | 17 | private static int deduplicatedCount = 0; 18 | private static int uniqueCount = 0; 19 | // private static int previousUniqueCount = 0; 20 | // private static boolean invalidated = false; 21 | 22 | private static ObjectOpenCustomHashSet POOL = new ObjectOpenCustomHashSet<>(8192, IntArrays.HASH_STRATEGY); 23 | 24 | public static int getSize() { 25 | return uniqueCount; 26 | // return invalidated ? previousUniqueCount + POOL.size() : POOL.size(); 27 | } 28 | 29 | public static int getDeduplicatedCount() { 30 | return deduplicatedCount; 31 | } 32 | 33 | public static int[] canonicalize(int[] vertexData) { 34 | if (POOL == null) { 35 | return vertexData; 36 | } 37 | synchronized (POOL) { 38 | deduplicatedCount++; 39 | return POOL.addOrGet(vertexData); 40 | } 41 | } 42 | 43 | public static int[] canonicalize(int[] vertexData, BakedQuad quad) { 44 | if (POOL == null) { 45 | return vertexData; 46 | } 47 | synchronized (POOL) { 48 | if (quad instanceof UnpackedBakedQuad) { 49 | return vertexData; // vertexData can be modified on piping UnpackedBakedQuads, hence no canonicalization 50 | } 51 | deduplicatedCount++; 52 | return POOL.addOrGet(vertexData); 53 | } 54 | } 55 | 56 | public static void invalidate() { 57 | if (POOL == null) { // Roost runs listeners again for some reason, this is a guard against that 58 | return; 59 | } 60 | uniqueCount = POOL.size(); 61 | // previousUniqueCount += POOL.size(); 62 | // POOL.clear(); 63 | // POOL.trim(); 64 | POOL = null; 65 | NormalLogger.instance.warn("Clearing NormalVertexDataPool"); 66 | } 67 | 68 | @SubscribeEvent 69 | public static void onDebugList(RenderGameOverlayEvent.Text event) { 70 | Minecraft minecraft = Minecraft.getMinecraft(); 71 | if (minecraft.gameSettings.showDebugInfo) { 72 | ArrayList list = event.getLeft(); 73 | list.add(String.format("%s%s%s: %s vertex data arrays processed. %s unique, %s deduplicated.", TextFormatting.AQUA, "", TextFormatting.RESET, deduplicatedCount, uniqueCount, deduplicatedCount - uniqueCount)); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/bakedquad/SupportingBakedQuad.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.bakedquad; 2 | 3 | import net.minecraft.client.renderer.block.model.BakedQuad; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | import net.minecraft.client.renderer.vertex.DefaultVertexFormats; 6 | import net.minecraft.client.renderer.vertex.VertexFormat; 7 | import net.minecraft.util.EnumFacing; 8 | import net.minecraftforge.fml.relauncher.Side; 9 | import net.minecraftforge.fml.relauncher.SideOnly; 10 | 11 | /** 12 | * Made for classes that extends vanilla BakedQuad, since NormalASM patches a lot of it, 13 | * Some extending classes may use the protected variables that were removed. 14 | * This class is to be the bridging class that they extend on. 15 | */ 16 | @SideOnly(Side.CLIENT) 17 | public class SupportingBakedQuad extends BakedQuad { 18 | 19 | protected final EnumFacing face; 20 | protected final boolean applyDiffuseLighting; 21 | protected final int tintIndex; 22 | 23 | public SupportingBakedQuad(int[] vertexDataIn, int tintIndexIn, EnumFacing faceIn, TextureAtlasSprite spriteIn, boolean applyDiffuseLighting, VertexFormat format) { 24 | super(vertexDataIn, tintIndexIn, faceIn, spriteIn, applyDiffuseLighting, format); 25 | this.face = faceIn; 26 | this.applyDiffuseLighting = applyDiffuseLighting; 27 | this.tintIndex = tintIndexIn; 28 | } 29 | 30 | public SupportingBakedQuad(int[] vertexDataIn, int tintIndexIn, EnumFacing faceIn, TextureAtlasSprite spriteIn) { 31 | this(vertexDataIn, tintIndexIn, faceIn, spriteIn, true, DefaultVertexFormats.ITEM); 32 | } 33 | 34 | @Override 35 | public EnumFacing getFace() { 36 | return face; 37 | } 38 | 39 | @Override 40 | public int getTintIndex() { 41 | return tintIndex; 42 | } 43 | 44 | @Override 45 | public boolean hasTintIndex() { 46 | return tintIndex != -1; 47 | } 48 | 49 | @Override 50 | public boolean shouldApplyDiffuseLighting() { 51 | return applyDiffuseLighting; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/NormalIncompatibilityHandler.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client; 2 | 3 | import net.minecraft.client.gui.FontRenderer; 4 | import net.minecraft.client.gui.GuiErrorScreen; 5 | import net.minecraftforge.fml.client.CustomModLoadingErrorDisplayException; 6 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 7 | import net.minecraftforge.fml.relauncher.Side; 8 | import net.minecraftforge.fml.relauncher.SideOnly; 9 | 10 | import java.util.List; 11 | 12 | public class NormalIncompatibilityHandler { 13 | 14 | public static void normalHaetPizza(List messages) { 15 | throw FMLLaunchHandler.side() == Side.SERVER ? new RuntimeException(String.join(",", messages)) : new Exception(messages); 16 | } 17 | 18 | @SideOnly(Side.CLIENT) 19 | private static class Exception extends CustomModLoadingErrorDisplayException { 20 | 21 | private final List messages; 22 | 23 | public Exception(List messages) { 24 | this.messages = messages; 25 | } 26 | 27 | @Override 28 | public void initGui(GuiErrorScreen errorScreen, FontRenderer fontRenderer) { } 29 | 30 | @Override 31 | public void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int mouseRelX, int mouseRelY, float tickTime) { 32 | int x = errorScreen.width / 2; 33 | int y = 75; 34 | for (String message : messages) { 35 | errorScreen.drawCenteredString(fontRenderer, message, x, y, 0xFFFFFF); 36 | y += 15; 37 | } 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/mcfixes/SkinDataReleaser.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.mcfixes; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.ThreadDownloadImageData; 5 | import net.minecraft.client.renderer.texture.ITextureObject; 6 | import net.minecraft.util.ResourceLocation; 7 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 8 | import net.minecraftforge.fml.common.network.FMLNetworkEvent; 9 | import mirror.normalasm.NormalLogger; 10 | import mirror.normalasm.common.internal.mixins.TextureManagerAccessor; 11 | 12 | import java.util.Iterator; 13 | import java.util.Map; 14 | import java.util.Map.Entry; 15 | 16 | public class SkinDataReleaser { 17 | 18 | @SubscribeEvent 19 | public static void onClientDisconnect(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) { 20 | Minecraft.getMinecraft().addScheduledTask(() -> { 21 | Map textureObjects = ((TextureManagerAccessor) Minecraft.getMinecraft().getTextureManager()).getMapTextureObjects(); 22 | if (textureObjects != null) { 23 | int count = 0; 24 | Iterator> entryIter = textureObjects.entrySet().iterator(); 25 | while (entryIter.hasNext()) { 26 | Entry entry = entryIter.next(); 27 | if (entry.getValue() instanceof ThreadDownloadImageData) { 28 | if (entry.getKey().getPath().startsWith("skins/")) { 29 | ((ThreadDownloadImageData) entry.getValue()).deleteGlTexture(); 30 | entryIter.remove(); 31 | NormalLogger.instance.debug("Released {} texture", entry.getKey()); 32 | count++; 33 | } 34 | } 35 | } 36 | NormalLogger.instance.info("Released {} skin textures", count); 37 | } 38 | }); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/models/MultipartBakedModelCache.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.models; 2 | 3 | import com.google.common.base.Predicate; 4 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 5 | import net.minecraft.block.state.IBlockState; 6 | import net.minecraft.client.renderer.block.model.IBakedModel; 7 | import net.minecraft.client.renderer.block.model.MultipartBakedModel; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * TODO: Not used at the moment, will be activated with the Deduplicator when that is complete 13 | */ 14 | public class MultipartBakedModelCache { 15 | 16 | public static int total = 0; 17 | public static int unique = 0; 18 | 19 | private static final Map, IBakedModel>, MultipartBakedModel> KNOWN_MULTIPART_MODELS = new Object2ObjectOpenHashMap<>(32); 20 | 21 | public static MultipartBakedModel makeMultipartModel(Map, IBakedModel> selectors) { 22 | MultipartBakedModel multipartBakedModel = KNOWN_MULTIPART_MODELS.get(selectors); 23 | total++; 24 | if (multipartBakedModel == null) { 25 | unique++; 26 | KNOWN_MULTIPART_MODELS.put(selectors, multipartBakedModel = new MultipartBakedModel(selectors)); 27 | } 28 | return multipartBakedModel; 29 | // return KNOWN_MULTIPART_MODELS.computeIfAbsent(selectors, MultipartBakedModel::new); 30 | } 31 | 32 | public static void destroyCache() { 33 | KNOWN_MULTIPART_MODELS.clear(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/models/bakedquad/mixins/HaxMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.models.bakedquad.mixins; 2 | 3 | import com.google.gson.GsonBuilder; 4 | import epicsquid.mysticallib.hax.*; 5 | import net.minecraft.client.renderer.block.model.*; 6 | import net.minecraftforge.fml.common.ObfuscationReflectionHelper; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import org.spongepowered.asm.mixin.Pseudo; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | import java.lang.reflect.Field; 13 | import java.lang.reflect.Modifier; 14 | 15 | @Pseudo 16 | @Mixin(value = Hax.class, remap = false) 17 | public class HaxMixin { 18 | 19 | @Shadow public static Field field_ModelBakery_blockModelShapes; 20 | 21 | /** 22 | * @author Rongmario 23 | * @reason What the fuck? Half of these fields aren't even being used, and most of their application fucking sucks. 24 | */ 25 | @Overwrite 26 | public static void init() throws IllegalAccessException, NoSuchFieldException, SecurityException, IllegalArgumentException { 27 | Field f = ObfuscationReflectionHelper.findField(ModelBlock.class, "field_178319_a"); 28 | f.setAccessible(true); 29 | Field modifiersField = Field.class.getDeclaredField("modifiers"); 30 | modifiersField.setAccessible(true); 31 | modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); 32 | f.set(null, new GsonBuilder() 33 | .registerTypeAdapter(ModelBlock.class, new ModelBlock.Deserializer()) 34 | .registerTypeAdapter(BlockPart.class, new BPDeserializer()) 35 | .registerTypeAdapter(BlockPartFace.class, new BPFDeserializer()) 36 | .registerTypeAdapter(BlockFaceUV.class, new BFUVDeserializer()) 37 | .registerTypeAdapter(ItemTransformVec3f.class, new ITV3FDeserializer()) 38 | .registerTypeAdapter(ItemCameraTransforms.class, new ICTDeserializer()) 39 | .registerTypeAdapter(ItemOverride.class, new IODeserializer()) 40 | .create()); 41 | field_ModelBakery_blockModelShapes = ObfuscationReflectionHelper.findField(ModelBakery.class, "field_177610_k"); 42 | field_ModelBakery_blockModelShapes.setAccessible(true); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/rendering/mixins/VisGraphMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.rendering.mixins; 2 | 3 | import it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue; 4 | import net.minecraft.client.renderer.chunk.VisGraph; 5 | import net.minecraft.util.EnumFacing; 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | import java.util.BitSet; 12 | import java.util.EnumSet; 13 | import java.util.Set; 14 | 15 | @Mixin(VisGraph.class) 16 | public abstract class VisGraphMixin { 17 | 18 | @Shadow @Final private BitSet bitSet; 19 | 20 | @Shadow protected abstract void addEdges(int pos, Set p_178610_2_); 21 | @Shadow protected abstract int getNeighborIndexAtFace(int pos, EnumFacing facing); 22 | 23 | /** 24 | * @author Rongmario 25 | * @reason No unboxing business 26 | */ 27 | @Overwrite 28 | private Set floodFill(int pos) { 29 | Set set = EnumSet.noneOf(EnumFacing.class); 30 | IntArrayFIFOQueue queue = new IntArrayFIFOQueue(); 31 | queue.enqueue(pos); 32 | this.bitSet.set(pos, true); 33 | while (!queue.isEmpty()) { 34 | int i = queue.dequeueInt(); 35 | this.addEdges(i, set); 36 | for (EnumFacing facing : EnumFacing.VALUES) { 37 | int j = this.getNeighborIndexAtFace(i, facing); 38 | if (j >= 0 && !this.bitSet.get(j)) { 39 | this.bitSet.set(j, true); 40 | queue.enqueue(j); 41 | } 42 | } 43 | } 44 | return set; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/screenshot/ScreenshotListener.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.screenshot; 2 | 3 | import net.minecraftforge.client.event.ScreenshotEvent; 4 | import net.minecraftforge.fml.common.eventhandler.EventPriority; 5 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 6 | import mirror.normalasm.NormalLogger; 7 | 8 | import java.awt.*; 9 | import java.awt.datatransfer.*; 10 | 11 | public class ScreenshotListener { 12 | 13 | @SubscribeEvent(priority = EventPriority.LOWEST) 14 | public static void onScreenshot(ScreenshotEvent event) { 15 | if (!event.isCanceled() && event.getScreenshotFile() != null) { 16 | NormalLogger.instance.info("Copied screenshot {} to clipboard!", event.getScreenshotFile().getName()); 17 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new TransferableImage(event.getImage()), null); 18 | } 19 | } 20 | 21 | private static class TransferableImage implements Transferable { 22 | 23 | final Image i; 24 | 25 | TransferableImage(Image i) { 26 | this.i = i; 27 | } 28 | 29 | @Override 30 | public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { 31 | if (flavor.equals(DataFlavor.imageFlavor) && i != null) { 32 | return i; 33 | } else { 34 | throw new UnsupportedFlavorException(flavor); 35 | } 36 | } 37 | 38 | @Override 39 | public DataFlavor[] getTransferDataFlavors() { 40 | DataFlavor[] flavors = new DataFlavor[1]; 41 | flavors[0] = DataFlavor.imageFlavor; 42 | return flavors; 43 | } 44 | 45 | @Override 46 | public boolean isDataFlavorSupported(DataFlavor flavor) { 47 | return flavor.equals(DataFlavor.imageFlavor); 48 | } 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/screenshot/ScreenshotThread.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.screenshot; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.util.text.ITextComponent; 5 | import net.minecraft.util.text.TextComponentString; 6 | import net.minecraft.util.text.TextComponentTranslation; 7 | import net.minecraft.util.text.event.ClickEvent; 8 | import mirror.normalasm.NormalLogger; 9 | 10 | import javax.annotation.Nullable; 11 | import javax.imageio.ImageIO; 12 | import java.awt.image.BufferedImage; 13 | import java.io.File; 14 | 15 | public class ScreenshotThread extends Thread { 16 | 17 | public ScreenshotThread(File screenshotFile, BufferedImage screenshot, @Nullable ITextComponent eventResultMessage) { 18 | super(() -> { 19 | Minecraft mc = Minecraft.getMinecraft(); 20 | try { 21 | ImageIO.write(screenshot, "png", screenshotFile); 22 | if (eventResultMessage != null) { 23 | mc.addScheduledTask(() -> mc.ingameGUI.getChatGUI().printChatMessage(eventResultMessage)); 24 | return; 25 | } 26 | ITextComponent fileName = new TextComponentString(screenshotFile.getName()); 27 | fileName.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, screenshotFile.getAbsolutePath())); 28 | fileName.getStyle().setUnderlined(true); 29 | mc.addScheduledTask(() -> mc.ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("screenshot.success", fileName))); 30 | } catch (Throwable t) { 31 | NormalLogger.instance.warn("Couldn't save screenshot", t); 32 | mc.addScheduledTask(() -> mc.ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("screenshot.failure", t.getMessage()))); 33 | } 34 | }, "NormalScreenshotThread"); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/screenshot/mixins/MinecraftMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.screenshot.mixins; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.GuiNewChat; 5 | import net.minecraft.client.shader.Framebuffer; 6 | import net.minecraft.util.ScreenShotHelper; 7 | import net.minecraft.util.text.ITextComponent; 8 | import net.minecraft.util.text.TextComponentTranslation; 9 | import net.minecraftforge.client.ForgeHooksClient; 10 | import net.minecraftforge.client.event.ScreenshotEvent; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Redirect; 14 | import mirror.normalasm.client.screenshot.ScreenshotThread; 15 | 16 | import java.awt.image.BufferedImage; 17 | import java.io.File; 18 | import java.io.IOException; 19 | 20 | @Mixin(Minecraft.class) 21 | public class MinecraftMixin { 22 | 23 | @Redirect(method = "dispatchKeypresses", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ScreenShotHelper;saveScreenshot(Ljava/io/File;IILnet/minecraft/client/shader/Framebuffer;)Lnet/minecraft/util/text/ITextComponent;", ordinal = 0)) 24 | private ITextComponent runAsyncScreenshotProcessing(File gameDir, int width, int height, Framebuffer buffer) { 25 | try { 26 | BufferedImage screenshot = ScreenShotHelper.createScreenshot(width, height, buffer); 27 | File screenshotDir = new File(gameDir, "screenshots"); 28 | screenshotDir.mkdir(); 29 | File screenshotFile = ScreenShotHelperInvoker.invokeGetTimestampedPNGFileForDirectory(screenshotDir).getCanonicalFile(); 30 | ScreenshotEvent event = ForgeHooksClient.onScreenshot(screenshot, screenshotFile); 31 | if (event.isCanceled()) { 32 | return event.getCancelMessage(); 33 | } 34 | new ScreenshotThread(event.getScreenshotFile(), screenshot, event.getResultMessage()).start(); 35 | return null; 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | return new TextComponentTranslation("screenshot.failure", e.getMessage()); 39 | } 40 | } 41 | 42 | @Redirect(method = "dispatchKeypresses", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;printChatMessage(Lnet/minecraft/util/text/ITextComponent;)V")) 43 | private void redirectPrintScreenshotPathInChat(GuiNewChat chat, ITextComponent text) { } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/screenshot/mixins/ScreenShotHelperInvoker.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.screenshot.mixins; 2 | 3 | import net.minecraft.util.ScreenShotHelper; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Invoker; 6 | 7 | import java.io.File; 8 | 9 | @Mixin(ScreenShotHelper.class) 10 | public interface ScreenShotHelperInvoker { 11 | 12 | @Invoker 13 | static File invokeGetTimestampedPNGFileForDirectory(File gameDirectory) { 14 | throw new AssertionError(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/screenshot/mixins/ScreenShotHelperMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.screenshot.mixins; 2 | 3 | import net.minecraft.client.renderer.GlStateManager; 4 | import net.minecraft.client.renderer.OpenGlHelper; 5 | import net.minecraft.client.renderer.texture.TextureUtil; 6 | import net.minecraft.client.shader.Framebuffer; 7 | import net.minecraft.util.ScreenShotHelper; 8 | import org.lwjgl.BufferUtils; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Overwrite; 11 | 12 | import java.awt.image.BufferedImage; 13 | import java.nio.IntBuffer; 14 | 15 | @Mixin(ScreenShotHelper.class) 16 | public class ScreenShotHelperMixin { 17 | 18 | /** 19 | * @author Rongmario 20 | * @reason Keep int array + buffer on the stack 21 | */ 22 | @Overwrite 23 | public static BufferedImage createScreenshot(int width, int height, Framebuffer framebufferIn) { 24 | boolean fbe = OpenGlHelper.isFramebufferEnabled(); 25 | if (fbe) { 26 | width = framebufferIn.framebufferTextureWidth; 27 | height = framebufferIn.framebufferTextureHeight; 28 | } 29 | int i = width * height; 30 | IntBuffer pixelBuffer = BufferUtils.createIntBuffer(i); 31 | GlStateManager.glPixelStorei(3333, 1); 32 | GlStateManager.glPixelStorei(3317, 1); 33 | if (fbe) { 34 | GlStateManager.bindTexture(framebufferIn.framebufferTexture); 35 | GlStateManager.glGetTexImage(3553, 0, 32993, 33639, pixelBuffer); 36 | } else { 37 | GlStateManager.glReadPixels(0, 0, width, height, 32993, 33639, pixelBuffer); 38 | } 39 | int[] pixelValues = new int[i]; 40 | pixelBuffer.get(pixelValues); 41 | TextureUtil.processPixelValues(pixelValues, width, height); 42 | BufferedImage bufferedimage = new BufferedImage(width, height, 1); 43 | bufferedimage.setRGB(0, 0, width, height, pixelValues, 0, width); 44 | return bufferedimage; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/searchtree/JEIRedirectSearchTree.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.searchtree; 2 | 3 | import mezz.jei.Internal; 4 | import mezz.jei.gui.ingredients.IIngredientListElement; 5 | import net.minecraft.client.util.SearchTree; 6 | import net.minecraft.item.ItemStack; 7 | import mirror.normalasm.client.searchtree.mixins.mod.IngredientFilterInvoker; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class JEIRedirectSearchTree extends SearchTree { 14 | 15 | private String lastSearch = ""; 16 | private final List resultsCache = new ArrayList<>(); 17 | 18 | @SuppressWarnings("ConstantConditions") 19 | public JEIRedirectSearchTree() { 20 | super(null, null); 21 | this.byName = null; 22 | this.byId = null; 23 | } 24 | 25 | @Override 26 | public void recalculate() { } 27 | 28 | @Override 29 | public void add(ItemStack element) { } 30 | 31 | @Override 32 | @SuppressWarnings("unchecked") 33 | public List search(String searchText) { 34 | if (lastSearch.equals(searchText)) { 35 | return resultsCache; 36 | } 37 | try { 38 | resultsCache.clear(); 39 | for (IIngredientListElement element : ((IngredientFilterInvoker) Internal.getIngredientFilter()).invokeGetIngredientListUncached(searchText)) { 40 | if (element.getIngredient() instanceof ItemStack) { 41 | resultsCache.add((ItemStack) element.getIngredient()); 42 | } 43 | } 44 | lastSearch = searchText; 45 | return resultsCache; 46 | } catch (Throwable t) { 47 | return Collections.emptyList(); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/searchtree/mixins/mod/IngredientFilterInvoker.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.searchtree.mixins.mod; 2 | 3 | import mezz.jei.gui.ingredients.IIngredientListElement; 4 | import mezz.jei.ingredients.IngredientFilter; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Invoker; 7 | 8 | import java.util.List; 9 | 10 | @Mixin(value = IngredientFilter.class, remap = false) 11 | public interface IngredientFilterInvoker { 12 | 13 | @Invoker 14 | List invokeGetIngredientListUncached(String filterText); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/searchtree/mixins/vanilla/MinecraftMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.searchtree.mixins.vanilla; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.recipebook.RecipeList; 5 | import net.minecraft.client.util.ITooltipFlag.TooltipFlags; 6 | import net.minecraft.client.util.SearchTree; 7 | import net.minecraft.client.util.SearchTreeManager; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.util.text.TextFormatting; 10 | import net.minecraftforge.fml.common.Loader; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Overwrite; 13 | import org.spongepowered.asm.mixin.Shadow; 14 | import mirror.normalasm.client.searchtree.JEIRedirectSearchTree; 15 | 16 | import java.util.Collections; 17 | import java.util.Objects; 18 | import java.util.stream.Collectors; 19 | 20 | @Mixin(Minecraft.class) 21 | public class MinecraftMixin { 22 | 23 | @Shadow private SearchTreeManager searchTreeManager; 24 | 25 | /** 26 | * @author Rongmario 27 | * @reason Use JEIRedirectSearchTree 28 | */ 29 | @Overwrite 30 | public void populateSearchTreeManager() { 31 | final SearchTree recipeSearchTree = new SearchTree<>( 32 | rl -> () -> rl.getRecipes().stream() 33 | .flatMap((r) -> r.getRecipeOutput().getTooltip(null, TooltipFlags.NORMAL).stream()) 34 | .map(TextFormatting::getTextWithoutFormattingCodes) 35 | .filter(Objects::nonNull) 36 | .map(String::trim) 37 | .filter(tooltip -> !tooltip.isEmpty()) 38 | .iterator(), 39 | rl -> () -> rl.getRecipes().stream() 40 | .map((r) -> r.getRecipeOutput().getItem().getRegistryName()) 41 | .iterator() 42 | ); 43 | final SearchTree itemSearchTree = Loader.isModLoaded("jei") ? 44 | new JEIRedirectSearchTree() : 45 | new SearchTree<>(stack -> 46 | stack.getTooltip(null, TooltipFlags.NORMAL) 47 | .stream() 48 | .map(TextFormatting::getTextWithoutFormattingCodes) 49 | .map(String::trim) 50 | .filter(tooltip -> !tooltip.isEmpty()) 51 | .collect(Collectors.toList()), 52 | stack -> Collections.singleton(stack.getItem().getRegistryName())); 53 | this.searchTreeManager.register(SearchTreeManager.RECIPES, recipeSearchTree); 54 | this.searchTreeManager.register(SearchTreeManager.ITEMS, itemSearchTree); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/FloorUV.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand; 2 | 3 | public class FloorUV { 4 | 5 | public static FloorUV of(float u, float v) { 6 | return new FloorUV(u, v); 7 | } 8 | 9 | public final float u, v; 10 | 11 | private FloorUV(float u, float v) { 12 | this.u = u; 13 | this.v = v; 14 | } 15 | 16 | @Override 17 | public int hashCode() { 18 | long bits = 1L; 19 | bits = 31L * bits + (long) Float.floatToIntBits(u); 20 | bits = 31L * bits + (long) Float.floatToIntBits(v); 21 | return (int) (bits ^ (bits >> 32)); 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (!(o instanceof FloorUV)) { 27 | return false; 28 | } 29 | FloorUV uv = (FloorUV) o; 30 | return this.u == uv.u && this.v == uv.v; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/IAnimatedSpriteActivator.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand; 2 | 3 | public interface IAnimatedSpriteActivator { 4 | 5 | boolean isActive(); 6 | 7 | void setActive(boolean active); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/IAnimatedSpritePrimer.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand; 2 | 3 | import net.minecraft.client.renderer.chunk.CompiledChunk; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | 6 | import javax.annotation.Nullable; 7 | 8 | public interface IAnimatedSpritePrimer { 9 | 10 | ThreadLocal CURRENT_COMPILED_CHUNK = ThreadLocal.withInitial(() -> CompiledChunk.DUMMY); 11 | 12 | ThreadLocal PRIMED = ThreadLocal.withInitial(() -> false); 13 | 14 | void addAnimatedSprite(float u, float v); 15 | 16 | default void registerUVRanges(float minU, float minV, TextureAtlasSprite sprite) { } 17 | 18 | @Nullable default TextureAtlasSprite getAnimatedSprite(float u, float v) { 19 | return null; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/IBufferPrimerConfigurator.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand; 2 | 3 | public interface IBufferPrimerConfigurator { 4 | 5 | void setPrimer(IAnimatedSpritePrimer primer); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/ICompiledChunkExpander.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand; 2 | 3 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 4 | import org.apache.commons.lang3.tuple.Pair; 5 | 6 | import javax.annotation.Nullable; 7 | import java.util.Set; 8 | 9 | public interface ICompiledChunkExpander { 10 | 11 | @Nullable 12 | @Deprecated 13 | default Set> getVisibleTexturesCoords() { 14 | return null; 15 | } 16 | 17 | Set getVisibleTextures(); 18 | 19 | @Deprecated 20 | default void resolve(Set visibleTextures) { 21 | 22 | } 23 | 24 | void resolve(TextureAtlasSprite sprite); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/IVertexLighterExpander.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand; 2 | 3 | public interface IVertexLighterExpander { 4 | 5 | T primeForDispatch(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/BlockFluidRendererMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.BlockFluidRenderer; 4 | import net.minecraft.client.renderer.chunk.CompiledChunk; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.ModifyVariable; 9 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpritePrimer; 10 | import mirror.normalasm.client.sprite.ondemand.ICompiledChunkExpander; 11 | 12 | @Mixin(BlockFluidRenderer.class) 13 | public class BlockFluidRendererMixin { 14 | 15 | @ModifyVariable(method = "renderFluid", at = @At(value = "CONSTANT", args = "floatValue=0.001", ordinal = 1), ordinal = 0) 16 | private TextureAtlasSprite afterTextureDetermined(TextureAtlasSprite texture) { 17 | CompiledChunk chunk = IAnimatedSpritePrimer.CURRENT_COMPILED_CHUNK.get(); 18 | if (chunk != null) { 19 | ((ICompiledChunkExpander) chunk).resolve(texture); 20 | } 21 | return texture; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/BlockModelRendererMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.BlockModelRenderer; 4 | import net.minecraft.client.renderer.block.model.BakedQuad; 5 | import net.minecraft.client.renderer.chunk.CompiledChunk; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpritePrimer; 10 | import mirror.normalasm.client.sprite.ondemand.ICompiledChunkExpander; 11 | 12 | import java.util.List; 13 | 14 | @Mixin(BlockModelRenderer.class) 15 | public class BlockModelRendererMixin { 16 | 17 | @Redirect(method = "renderQuadsSmooth", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;", remap = false)) 18 | private Object sendAnimatedSprites$smooth(List list, int i) { 19 | BakedQuad bakedquad = (BakedQuad) list.get(i); 20 | if (bakedquad.getSprite().hasAnimationMetadata()) { 21 | CompiledChunk chunk = IAnimatedSpritePrimer.CURRENT_COMPILED_CHUNK.get(); 22 | if (chunk != null) { 23 | ((ICompiledChunkExpander) chunk).resolve(bakedquad.getSprite()); 24 | } 25 | } 26 | return bakedquad; 27 | } 28 | 29 | @SuppressWarnings("all") 30 | @Redirect(method = "renderQuadsFlat", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;", ordinal = 0)) 31 | private Object sendAnimatedSprites$flat(List list, int i) { 32 | BakedQuad bakedquad = list.get(i); 33 | if (bakedquad.getSprite().hasAnimationMetadata()) { 34 | CompiledChunk chunk = IAnimatedSpritePrimer.CURRENT_COMPILED_CHUNK.get(); 35 | if (chunk != CompiledChunk.DUMMY) { 36 | ((ICompiledChunkExpander) chunk).resolve(bakedquad.getSprite()); 37 | } 38 | } 39 | return bakedquad; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/ChunkCompileTaskGeneratorMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator; 4 | import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator.Type; 5 | import net.minecraft.client.renderer.chunk.CompiledChunk; 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpritePrimer; 11 | 12 | @Mixin(ChunkCompileTaskGenerator.class) 13 | public class ChunkCompileTaskGeneratorMixin { 14 | 15 | @Shadow @Final private Type type; 16 | 17 | @Shadow private CompiledChunk compiledChunk; 18 | 19 | /** 20 | * @author Rongmario 21 | * @reason Prime the current CompiledChunk to the ThreadLocal variable 22 | */ 23 | @Overwrite 24 | public void setCompiledChunk(CompiledChunk compiledChunk) { 25 | this.compiledChunk = compiledChunk; 26 | if (this.type == Type.REBUILD_CHUNK) { 27 | IAnimatedSpritePrimer.CURRENT_COMPILED_CHUNK.set(compiledChunk); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/CompiledChunkMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; 4 | import net.minecraft.client.renderer.chunk.CompiledChunk; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Unique; 8 | import mirror.normalasm.client.sprite.ondemand.ICompiledChunkExpander; 9 | 10 | import java.util.Set; 11 | 12 | @Mixin(CompiledChunk.class) 13 | public class CompiledChunkMixin implements ICompiledChunkExpander { 14 | 15 | @Unique private final Set visibleTextures = new ReferenceOpenHashSet<>(16); 16 | 17 | @Override 18 | public Set getVisibleTextures() { 19 | return visibleTextures; 20 | } 21 | 22 | @Override 23 | public void resolve(TextureAtlasSprite sprite) { 24 | this.visibleTextures.add(sprite); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/ContainerLocalRenderInformationAccessor.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.chunk.RenderChunk; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Accessor; 6 | 7 | @Mixin(targets = "net.minecraft.client.renderer.RenderGlobal$ContainerLocalRenderInformation") 8 | public interface ContainerLocalRenderInformationAccessor { 9 | 10 | @Accessor 11 | RenderChunk getRenderChunk(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/ForgeBlockModelRendererMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.color.BlockColors; 4 | import net.minecraftforge.client.model.pipeline.ForgeBlockModelRenderer; 5 | import net.minecraftforge.client.model.pipeline.VertexLighterFlat; 6 | import net.minecraftforge.client.model.pipeline.VertexLighterSmoothAo; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Mutable; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | import mirror.normalasm.client.sprite.ondemand.IVertexLighterExpander; 15 | 16 | @Mixin(value = ForgeBlockModelRenderer.class, remap = false) 17 | public class ForgeBlockModelRendererMixin { 18 | 19 | @Shadow @Final @Mutable private ThreadLocal lighterFlat; 20 | @Shadow @Final @Mutable private ThreadLocal lighterSmooth; 21 | 22 | @Inject(method = "", at = @At("RETURN")) 23 | private void afterInit(BlockColors colours, CallbackInfo ci) { 24 | this.lighterFlat = ThreadLocal.withInitial(() -> ((IVertexLighterExpander) new VertexLighterFlat(colours)).primeForDispatch()); 25 | this.lighterSmooth = ThreadLocal.withInitial(() -> ((IVertexLighterExpander) new VertexLighterSmoothAo(colours)).primeForDispatch()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/ItemRendererMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.ItemRenderer; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpriteActivator; 13 | 14 | @Mixin(ItemRenderer.class) 15 | public class ItemRendererMixin { 16 | 17 | @Shadow @Final public Minecraft mc; 18 | 19 | @Inject(method = "renderSuffocationOverlay", at = @At("HEAD")) 20 | private void beforeRenderBlockInHand(TextureAtlasSprite texture, CallbackInfo ci) { 21 | if (texture.hasAnimationMetadata()) { 22 | ((IAnimatedSpriteActivator) texture).setActive(true); 23 | } 24 | } 25 | 26 | @Inject(method = "renderFireInFirstPerson", at = @At("HEAD")) 27 | private void beforeRenderFireInFirstPerson(CallbackInfo ci) { 28 | // TODO: cache "minecraft:blocks/fire_layer_1", and refresh on RenderGlobal#onResourceManagerReload 29 | ((IAnimatedSpriteActivator) mc.getTextureMapBlocks().getAtlasSprite("minecraft:blocks/fire_layer_1")).setActive(true); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/RenderGlobalAccessor.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.RenderGlobal; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Accessor; 6 | 7 | import java.util.List; 8 | 9 | @Mixin(RenderGlobal.class) 10 | public interface RenderGlobalAccessor { 11 | 12 | @Accessor 13 | List getRenderInfos(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/RenderItemMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.BufferBuilder; 4 | import net.minecraft.client.renderer.RenderItem; 5 | import net.minecraft.client.renderer.block.model.BakedQuad; 6 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 7 | import net.minecraft.item.ItemStack; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 13 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpriteActivator; 14 | 15 | import java.util.List; 16 | 17 | @Mixin(RenderItem.class) 18 | public class RenderItemMixin { 19 | 20 | @Inject(method = "renderQuads", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/model/pipeline/LightUtil;renderQuadColor(Lnet/minecraft/client/renderer/BufferBuilder;Lnet/minecraft/client/renderer/block/model/BakedQuad;I)V"), 21 | locals = LocalCapture.CAPTURE_FAILHARD) 22 | public void beforeRenderItem(BufferBuilder renderer, List quads, int color, ItemStack stack, CallbackInfo ci, boolean flag, int i, int j, BakedQuad bakedquad) { 23 | TextureAtlasSprite sprite = bakedquad.getSprite(); 24 | if (sprite != null && sprite.hasAnimationMetadata()) { 25 | ((IAnimatedSpriteActivator) bakedquad.getSprite()).setActive(true); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/TextureAtlasSpriteMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Unique; 6 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpriteActivator; 7 | 8 | @Mixin(TextureAtlasSprite.class) 9 | public class TextureAtlasSpriteMixin implements IAnimatedSpriteActivator { 10 | 11 | @Unique private boolean normal$active; 12 | 13 | @Override 14 | public boolean isActive() { 15 | return normal$active; 16 | } 17 | 18 | @Override 19 | public void setActive(boolean active) { 20 | this.normal$active = active; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/TextureManagerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.texture.TextureManager; 4 | import net.minecraft.client.renderer.texture.TextureMap; 5 | import net.minecraft.util.ResourceLocation; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpritePrimer; 11 | 12 | @Mixin(TextureManager.class) 13 | public class TextureManagerMixin { 14 | 15 | @Inject(method = "bindTexture", at = @At("HEAD")) 16 | private void checkForMainSpriteSheet(ResourceLocation resource, CallbackInfo ci) { 17 | if (resource == TextureMap.LOCATION_BLOCKS_TEXTURE) { 18 | IAnimatedSpritePrimer.PRIMED.set(true); 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/client/sprite/ondemand/mixins/VertexLighterFlatMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.client.sprite.ondemand.mixins; 2 | 3 | import net.minecraft.client.renderer.chunk.CompiledChunk; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer; 6 | import net.minecraftforge.client.model.pipeline.VertexLighterFlat; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Unique; 9 | import mirror.normalasm.client.sprite.ondemand.IAnimatedSpritePrimer; 10 | import mirror.normalasm.client.sprite.ondemand.ICompiledChunkExpander; 11 | import mirror.normalasm.client.sprite.ondemand.IVertexLighterExpander; 12 | 13 | @Mixin(VertexLighterFlat.class) 14 | public abstract class VertexLighterFlatMixin extends QuadGatheringTransformer implements IVertexLighterExpander { 15 | 16 | @Unique private boolean primedForDispatch = false; 17 | 18 | @Override 19 | public Object primeForDispatch() { 20 | this.primedForDispatch = true; 21 | return this; 22 | } 23 | 24 | @Override 25 | public void setTexture(TextureAtlasSprite texture) { 26 | if (this.primedForDispatch && texture.hasAnimationMetadata()) { 27 | CompiledChunk chunk = IAnimatedSpritePrimer.CURRENT_COMPILED_CHUNK.get(); 28 | if (chunk != null) { 29 | ((ICompiledChunkExpander) chunk).resolve(texture); 30 | } 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/capability/astralsorcery/mixins/AmuletHolderCapabilityProviderAccessor.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.capability.astralsorcery.mixins; 2 | 3 | import hellfirepvp.astralsorcery.common.enchantment.amulet.AmuletHolderCapability; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Accessor; 6 | 7 | @Mixin(value = AmuletHolderCapability.Provider.class, remap = false) 8 | public interface AmuletHolderCapabilityProviderAccessor { 9 | 10 | @Accessor("defaultImpl") 11 | AmuletHolderCapability normalasm$defaultImplFastAccess(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/capability/astralsorcery/mixins/EnchantmentUpgradeHelperMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.capability.astralsorcery.mixins; 2 | 3 | import hellfirepvp.astralsorcery.common.enchantment.amulet.AmuletHolderCapability; 4 | import hellfirepvp.astralsorcery.common.enchantment.amulet.EnchantmentUpgradeHelper; 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.item.ItemStack; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import mirror.normalasm.api.IItemStackCapabilityInjector; 10 | import mirror.normalasm.api.ICapabilityDispatcherManipulator; 11 | 12 | @Mixin(value = EnchantmentUpgradeHelper.class, remap = false) 13 | public class EnchantmentUpgradeHelperMixin { 14 | 15 | /** 16 | * @author Rongmario 17 | * @reason Only apply AmuletHolderCapability when needed. 18 | */ 19 | @Overwrite 20 | public static void applyAmuletOwner(ItemStack tool, EntityPlayer wearer) { 21 | AmuletHolderCapability cap = tool.getCapability(AmuletHolderCapability.CAPABILITY_AMULET_HOLDER, null); 22 | if (cap == null) { 23 | AmuletHolderCapability.Provider provider = new AmuletHolderCapability.Provider(); 24 | ((IItemStackCapabilityInjector) (Object) tool).initDispatcher(AmuletHolderCapability.CAP_AMULETHOLDER_NAME, provider); 25 | ((AmuletHolderCapabilityProviderAccessor) provider).normalasm$defaultImplFastAccess().setHolderUUID(wearer.getUniqueID()); 26 | } else { 27 | cap.setHolderUUID(wearer.getUniqueID()); 28 | } 29 | } 30 | 31 | /** 32 | * @author Rongmario 33 | * @reason Remove capability when the stack no longer needs it 34 | */ 35 | @Overwrite 36 | private static void removeAmuletOwner(ItemStack tool) { 37 | AmuletHolderCapability cap = tool.getCapability(AmuletHolderCapability.CAPABILITY_AMULET_HOLDER, null); 38 | if (cap != null) { 39 | ((ICapabilityDispatcherManipulator) (Object) ((IItemStackCapabilityInjector) (Object) tool).getDispatcher()).stripCapability(AmuletHolderCapability.CAP_AMULETHOLDER_NAME, AmuletHolderCapability.CAPABILITY_AMULET_HOLDER, null, cap); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/CrashUtils.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.crash.CrashReport; 5 | import net.minecraft.util.ReportedException; 6 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 7 | import mirror.normalasm.NormalLogger; 8 | 9 | import java.io.File; 10 | import java.text.SimpleDateFormat; 11 | import java.util.Date; 12 | 13 | public final class CrashUtils { 14 | 15 | public static void crash(CrashReport report) { 16 | throw new ReportedException(report); 17 | } 18 | 19 | public static void warn(CrashReport report) { 20 | if (FMLLaunchHandler.side().isClient()) { 21 | outputReport(report); 22 | // Don't inline showWarningScreen, that will cause Java to load the GuiScreen 23 | // class on servers, because of the lambda! 24 | ((IMinecraftExtender) Minecraft.getMinecraft()).showWarningScreen(report); 25 | } else { 26 | NormalLogger.instance.fatal(report.getDescription(), report.getCrashCause()); 27 | } 28 | } 29 | 30 | public static void notify(CrashReport report) { 31 | if (FMLLaunchHandler.side().isClient()) { 32 | outputReport(report); 33 | ((IMinecraftExtender) Minecraft.getMinecraft()).makeErrorNotification(report); 34 | } else { 35 | NormalLogger.instance.fatal(report.getDescription(), report.getCrashCause()); 36 | } 37 | } 38 | 39 | public static void outputReport(CrashReport report) { 40 | try { 41 | if (report.getFile() == null) { 42 | String reportName = "crash-"; 43 | reportName += new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss").format(new Date()); 44 | reportName += Minecraft.getMinecraft().isCallingFromMinecraftThread() ? "-client" : "-server"; 45 | reportName += ".txt"; 46 | 47 | File reportsDir = FMLLaunchHandler.side().isClient() ? new File(Minecraft.getMinecraft().gameDir, "crash-reports") : new File("crash-reports"); 48 | File reportFile = new File(reportsDir, reportName); 49 | 50 | report.saveToFile(reportFile); 51 | } 52 | } catch (Throwable e) { 53 | NormalLogger.instance.fatal("Failed saving report", e); 54 | } 55 | NormalLogger.instance.fatal("Minecraft ran into a problem! " + (report.getFile() != null ? "Report saved to: " + report.getFile() : "Crash report could not be saved.") + "\n" + report.getCompleteReport()); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/GuiCrashScreen.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | import net.minecraft.client.gui.GuiMainMenu; 5 | import net.minecraft.client.gui.GuiOptionButton; 6 | import net.minecraft.client.resources.I18n; 7 | import net.minecraft.crash.CrashReport; 8 | import net.minecraftforge.fml.relauncher.Side; 9 | import net.minecraftforge.fml.relauncher.SideOnly; 10 | import mirror.normalasm.config.NormalConfig; 11 | 12 | @SideOnly(Side.CLIENT) 13 | public class GuiCrashScreen extends GuiProblemScreen { 14 | 15 | public GuiCrashScreen(CrashReport report) { 16 | super(report); 17 | } 18 | 19 | @Override 20 | public void initGui() { 21 | super.initGui(); 22 | GuiOptionButton mainMenuButton = new GuiOptionButton(0, width / 2 - 155, height / 4 + 120 + 12, I18n.format("gui.toTitle")); 23 | buttonList.add(mainMenuButton); 24 | if (!NormalConfig.instance.returnToMainMenuAfterCrash) { 25 | mainMenuButton.enabled = false; 26 | mainMenuButton.displayString = I18n.format("normalasm.gui.disabledByConfig"); 27 | } 28 | } 29 | 30 | @Override 31 | protected void actionPerformed(GuiButton button) { 32 | super.actionPerformed(button); 33 | if (button.id == 0) { 34 | mc.displayGuiScreen(new GuiMainMenu()); 35 | } 36 | } 37 | 38 | @Override 39 | public void drawScreen(int mouseX, int mouseY, float partialTicks) { // TODO: localize number of lines 40 | drawDefaultBackground(); 41 | drawCenteredString(fontRenderer, I18n.format("normalasm.crashscreen.title"), width / 2, height / 4 - 40, 0xFFFFFF); 42 | 43 | int textColor = 0xD0D0D0; 44 | int x = width / 2 - 155; 45 | int y = height / 4; 46 | 47 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.summary"), x, y, textColor); 48 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph1.line1"), x, y += 18, textColor); 49 | 50 | drawCenteredString(fontRenderer, getModListString(), width / 2, y += 11, 0xE0E000); 51 | 52 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph2.line1"), x, y += 11, textColor); 53 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph2.line2"), x, y += 9, textColor); 54 | 55 | drawCenteredString(fontRenderer, report.getFile() != null ? 56 | "\u00A7n" + report.getFile().getName() : 57 | I18n.format("normalasm.crashscreen.reportSaveFailed"), width / 2, y += 11, 0x00FF00); 58 | 59 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph3.line1"), x, y += 12, textColor); 60 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph3.line2"), x, y += 9, textColor); 61 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph3.line3"), x, y += 9, textColor); 62 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph3.line4"), x, y + 9, textColor); 63 | 64 | super.drawScreen(mouseX, mouseY, partialTicks); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/GuiInitErrorScreen.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | import net.minecraft.client.resources.I18n; 5 | import net.minecraft.crash.CrashReport; 6 | import net.minecraftforge.fml.relauncher.Side; 7 | import net.minecraftforge.fml.relauncher.SideOnly; 8 | 9 | @SideOnly(Side.CLIENT) 10 | public class GuiInitErrorScreen extends GuiProblemScreen { 11 | 12 | public GuiInitErrorScreen(CrashReport report) { 13 | super(report); 14 | } 15 | 16 | @Override 17 | public void initGui() { 18 | mc.setIngameNotInFocus(); 19 | buttonList.clear(); 20 | buttonList.add(new GuiButton(1, width / 2 - 155, height / 4 + 120 + 12, 310, 20, I18n.format("normalasm.gui.getLink"))); 21 | } 22 | 23 | @Override 24 | protected void actionPerformed(GuiButton button) { 25 | super.actionPerformed(button); 26 | } 27 | 28 | @Override 29 | public void drawScreen(int mouseX, int mouseY, float partialTicks) { // TODO: localize number of lines 30 | drawDefaultBackground(); 31 | drawCenteredString(fontRenderer, I18n.format("normalasm.initerrorscreen.title"), width / 2, height / 4 - 40, 0xFFFFFF); 32 | 33 | int textColor = 0xD0D0D0; 34 | int x = width / 2 - 155; 35 | int y = height / 4; 36 | 37 | drawString(fontRenderer, I18n.format("normalasm.initerrorscreen.summary"), x, y, textColor); 38 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph1.line1"), x, y += 18, textColor); 39 | 40 | drawCenteredString(fontRenderer, getModListString(), width / 2, y += 11, 0xE0E000); 41 | 42 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph2.line1"), x, y += 11, textColor); 43 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph2.line2"), x, y += 9, textColor); 44 | 45 | drawCenteredString(fontRenderer, report.getFile() != null ? 46 | "\u00A7n" + report.getFile().getName() : 47 | I18n.format("normalasm.crashscreen.reportSaveFailed"), width / 2, y += 11, 0x00FF00); 48 | 49 | drawString(fontRenderer, I18n.format("normalasm.initerrorscreen.paragraph3.line1"), x, y += 12, textColor); 50 | drawString(fontRenderer, I18n.format("normalasm.initerrorscreen.paragraph3.line2"), x, y += 9, textColor); 51 | drawString(fontRenderer, I18n.format("normalasm.initerrorscreen.paragraph3.line3"), x, y += 9, textColor); 52 | drawString(fontRenderer, I18n.format("normalasm.initerrorscreen.paragraph3.line4"), x, y + 9, textColor); 53 | 54 | super.drawScreen(mouseX, mouseY, partialTicks); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/GuiProblemScreen.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | import net.minecraft.client.gui.GuiConfirmOpenLink; 5 | import net.minecraft.client.gui.GuiScreen; 6 | import net.minecraft.client.resources.I18n; 7 | import net.minecraft.crash.CrashReport; 8 | import net.minecraftforge.fml.common.ModContainer; 9 | import net.minecraftforge.fml.relauncher.ReflectionHelper; 10 | import net.minecraftforge.fml.relauncher.Side; 11 | import net.minecraftforge.fml.relauncher.SideOnly; 12 | import org.apache.commons.lang3.StringUtils; 13 | import mirror.normalasm.NormalLogger; 14 | import mirror.normalasm.api.HasteUpload; 15 | 16 | import java.net.URI; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Set; 20 | 21 | @SideOnly(Side.CLIENT) 22 | public abstract class GuiProblemScreen extends GuiScreen { 23 | 24 | protected final CrashReport report; 25 | private String hasteLink = null; 26 | private String modListString; 27 | 28 | public GuiProblemScreen(CrashReport report) { 29 | this.report = report; 30 | } 31 | 32 | @Override 33 | public void initGui() { 34 | mc.setIngameNotInFocus(); 35 | buttonList.clear(); 36 | buttonList.add(new GuiButton(1, width / 2 - 155 + 160, height / 4 + 120 + 12, 150, 20, I18n.format("normalasm.gui.getLink"))); 37 | } 38 | 39 | @Override 40 | protected void actionPerformed(GuiButton button) { 41 | if (button.id == 1) { 42 | try { 43 | if (hasteLink == null) { 44 | hasteLink = HasteUpload.uploadToHaste(report.getCompleteReport()); 45 | } 46 | ReflectionHelper.findField(GuiScreen.class, "clickedLinkURI", "field_175286_t").set(this, new URI(hasteLink)); 47 | mc.displayGuiScreen(new GuiConfirmOpenLink(this, hasteLink, 31102009, false)); 48 | } catch (Throwable e) { 49 | NormalLogger.instance.error("Exception when crash menu button clicked:", e); 50 | button.displayString = I18n.format("normalasm.gui.failed"); 51 | button.enabled = false; 52 | } 53 | } 54 | } 55 | 56 | @Override 57 | protected void keyTyped(char typedChar, int keyCode) { } 58 | 59 | protected String getModListString() { 60 | if (modListString == null) { 61 | final Set suspectedMods = ((ICrashReportSuspectGetter) report).getSuspectedMods(); 62 | if (suspectedMods == null) { 63 | return modListString = I18n.format("normalasm.crashscreen.identificationErrored"); 64 | } 65 | List modNames = new ArrayList<>(); 66 | for (ModContainer mod : suspectedMods) { 67 | modNames.add(mod.getName()); 68 | } 69 | if (modNames.isEmpty()) { 70 | modListString = I18n.format("normalasm.crashscreen.unknownCause"); 71 | } else { 72 | modListString = StringUtils.join(modNames, ", "); 73 | } 74 | } 75 | return modListString; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/GuiWarningScreen.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | import net.minecraft.client.gui.GuiScreen; 5 | import net.minecraft.client.resources.I18n; 6 | import net.minecraft.crash.CrashReport; 7 | import net.minecraftforge.fml.relauncher.Side; 8 | import net.minecraftforge.fml.relauncher.SideOnly; 9 | 10 | @SideOnly(Side.CLIENT) 11 | public class GuiWarningScreen extends GuiProblemScreen { 12 | 13 | public GuiWarningScreen(CrashReport report, GuiScreen nextScreen) { 14 | super(report); 15 | } 16 | 17 | @Override 18 | public void initGui() { 19 | super.initGui(); 20 | buttonList.add(new GuiButton(0, width / 2 - 155, height / 4 + 120 + 12, 150, 20, I18n.format("normalasm.gui.keepPlaying"))); 21 | // TODO: Pause sounds too (see Minecraft.displayInGameMenu) 22 | } 23 | 24 | @Override 25 | protected void actionPerformed(GuiButton button) { 26 | super.actionPerformed(button); 27 | if (button.id == 0) { 28 | mc.displayGuiScreen(null); 29 | } 30 | } 31 | 32 | @Override 33 | public void drawScreen(int mouseX, int mouseY, float partialTicks) { // TODO: localize number of lines 34 | drawDefaultBackground(); 35 | drawCenteredString(fontRenderer, I18n.format("normalasm.warnscreen.title"), width / 2, height / 4 - 40, 0xFFFFFF); 36 | 37 | int textColor = 0xD0D0D0; 38 | int x = width / 2 - 155; 39 | int y = height / 4; 40 | 41 | y -= 20; 42 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.summary"), x, y, textColor); 43 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph1.line1"), x, y += 18, textColor); 44 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph1.line2"), x, y += 9, textColor); 45 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph1.line3"), x, y += 9, textColor); 46 | 47 | drawCenteredString(fontRenderer, getModListString(), width / 2, y += 11, 0xE0E000); 48 | 49 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph2.line1"), x, y += 11, textColor); 50 | drawString(fontRenderer, I18n.format("normalasm.crashscreen.paragraph2.line2"), x, y += 9, textColor); 51 | 52 | drawCenteredString(fontRenderer, report.getFile() != null ? 53 | "\u00A7n" + report.getFile().getName() : 54 | I18n.format("normalasm.crashscreen.reportSaveFailed"), width / 2, y += 11, 0x00FF00); 55 | 56 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph3.line1"), x, y += 12, textColor); 57 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph3.line2"), x, y += 9, textColor); 58 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph3.line3"), x, y += 9, textColor); 59 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph3.line4"), x, y += 9, textColor); 60 | drawString(fontRenderer, I18n.format("normalasm.warnscreen.paragraph3.line5"), x, y + 9, textColor); 61 | 62 | super.drawScreen(mouseX, mouseY, partialTicks); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/ICrashReportSuspectGetter.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraftforge.fml.common.ModContainer; 4 | 5 | import java.util.Set; 6 | 7 | public interface ICrashReportSuspectGetter { 8 | 9 | Set getSuspectedMods(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/IMinecraftExtender.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.crash.CrashReport; 4 | 5 | public interface IMinecraftExtender { 6 | 7 | boolean shouldCrashIntegratedServerNextTick(); 8 | 9 | void showWarningScreen(CrashReport report); 10 | 11 | void makeErrorNotification(CrashReport report); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/IStateful.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import it.unimi.dsi.fastutil.objects.ReferenceArraySet; 4 | 5 | import java.lang.ref.WeakReference; 6 | import java.util.Iterator; 7 | import java.util.Set; 8 | 9 | /** 10 | * Objects that implement and register with this will be able to reset to a fresh or even earlier state after a crash. 11 | */ 12 | public interface IStateful { 13 | 14 | Set> INSTANCES = new ReferenceArraySet<>(); 15 | 16 | static void resetAll() { 17 | Iterator> iterator = INSTANCES.iterator(); 18 | while (iterator.hasNext()) { 19 | IStateful reference = iterator.next().get(); 20 | if (reference != null) { 21 | reference.resetState(); 22 | } else { 23 | iterator.remove(); 24 | } 25 | } 26 | } 27 | 28 | default void register() { 29 | INSTANCES.add(new WeakReference<>(this)); 30 | } 31 | 32 | void resetState(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/ProblemToast.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes; 2 | 3 | import net.minecraft.client.gui.toasts.GuiToast; 4 | import net.minecraft.client.gui.toasts.IToast; 5 | import net.minecraft.client.renderer.GlStateManager; 6 | import net.minecraft.client.resources.I18n; 7 | import net.minecraft.crash.CrashReport; 8 | import net.minecraftforge.fml.common.ModContainer; 9 | 10 | import java.util.Set; 11 | 12 | public class ProblemToast implements IToast { 13 | 14 | private static final int ERROR_REPORT_DURATION = 30000; 15 | 16 | public final CrashReport report; 17 | 18 | public boolean hide; 19 | 20 | private String suspectedModString; 21 | 22 | public ProblemToast(CrashReport report) { 23 | this.report = report; 24 | } 25 | 26 | @Override 27 | public IToast.Visibility draw(GuiToast toastGui, long delta) { 28 | if (hide) { 29 | return Visibility.HIDE; 30 | } 31 | toastGui.getMinecraft().getTextureManager().bindTexture(TEXTURE_TOASTS); 32 | GlStateManager.color(1.0F, 1.0F, 1.0F); 33 | toastGui.drawTexturedModalRect(0, 0, 0, 96, 160, 32); 34 | Object cause = getModCause(); 35 | toastGui.getMinecraft().fontRenderer.drawString(cause.equals("") ? 36 | I18n.format("normalasm.notification.title.unknown") : 37 | I18n.format("normalasm.notification.title.mod", cause), 5, 7, 0xFF000000); 38 | toastGui.getMinecraft().fontRenderer.drawString(I18n.format("normalasm.notification.description"), 5, 18, 0xFF500050); 39 | return delta >= ERROR_REPORT_DURATION ? IToast.Visibility.HIDE : IToast.Visibility.SHOW; 40 | } 41 | 42 | private Object getModCause() { 43 | if (suspectedModString == null) { 44 | Set suspectedMods = ((ICrashReportSuspectGetter) report).getSuspectedMods(); 45 | suspectedModString = suspectedMods.isEmpty() ? "" : suspectedMods.iterator().next().getName(); 46 | } 47 | return suspectedModString; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/BufferBuilderMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.client.renderer.BufferBuilder; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Shadow; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | import mirror.normalasm.common.crashes.IStateful; 10 | 11 | @Mixin(BufferBuilder.class) 12 | public abstract class BufferBuilderMixin implements IStateful { 13 | 14 | @Shadow public boolean isDrawing; 15 | 16 | @Shadow public abstract void finishDrawing(); 17 | 18 | @Inject(method = "", at = @At(value = "RETURN")) 19 | public void onInit(int bufferSizeIn, CallbackInfo ci) { 20 | register(); 21 | } 22 | 23 | @Override 24 | public void resetState() { 25 | if (isDrawing) { 26 | finishDrawing(); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/CrashReportCategoryMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.crash.CrashReportCategory; 4 | import mirror.normalasm.api.StacktraceDeobfuscator; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Overwrite; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 12 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 13 | 14 | import java.util.List; 15 | 16 | @Mixin(CrashReportCategory.class) 17 | public class CrashReportCategoryMixin { 18 | 19 | @Shadow @Final private String name; 20 | @Shadow @Final private List children; 21 | 22 | @Inject(method = "getPrunedStackTrace", at = @At(value = "INVOKE", target = "Ljava/lang/System;arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V", remap = false), locals = LocalCapture.CAPTURE_FAILHARD) 23 | private void beforeCopyingStackTrace(int size, CallbackInfoReturnable cir, StackTraceElement[] stackTrace) { 24 | StacktraceDeobfuscator.deobfuscateStacktrace(stackTrace); 25 | } 26 | 27 | /** 28 | * @author VanillaFix 29 | * @reason Improve formatting 30 | */ 31 | @Overwrite 32 | public void appendToStringBuilder(StringBuilder builder) { 33 | builder.append("-- ").append(name).append(" --\n"); 34 | for (CrashReportCategory_EntryInvoker entry : children) { 35 | String sectionIndent = " "; 36 | builder.append(sectionIndent).append(entry.invokeGetKey()).append(": "); 37 | StringBuilder indent = new StringBuilder(sectionIndent + " "); 38 | for (char ignored : entry.invokeGetKey().toCharArray()) { 39 | indent.append(" "); 40 | } 41 | boolean first = true; 42 | for (String line : entry.invokeGetValue().trim().split("\n")) { 43 | if (!first) { 44 | builder.append("\n").append(indent); 45 | } 46 | first = false; 47 | if (line.startsWith("\t")) { 48 | line = line.substring(1); 49 | } 50 | builder.append(line.replace("\t", "")); 51 | } 52 | builder.append("\n"); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/CrashReportCategory_EntryInvoker.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import org.spongepowered.asm.mixin.gen.Invoker; 5 | 6 | @Mixin(targets = "net.minecraft.crash.CrashReportCategory$Entry") 7 | public interface CrashReportCategory_EntryInvoker { 8 | 9 | @Invoker 10 | String invokeGetKey(); 11 | 12 | @Invoker 13 | String invokeGetValue(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/EntityMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.crash.CrashReportCategory; 4 | import net.minecraft.entity.Entity; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(Entity.class) 12 | public class EntityMixin { 13 | 14 | @Inject(method = "addEntityCrashInfo", at = @At("TAIL")) 15 | private void onAddEntityCrashInfo(CrashReportCategory category, CallbackInfo ci) { 16 | category.addDetail("Entity NBT", () -> ((Entity) (Object) this).writeToNBT(new NBTTagCompound()).toString()); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/IntegratedServerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.crash.CrashReport; 5 | import net.minecraft.server.integrated.IntegratedServer; 6 | import net.minecraft.util.ReportedException; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | import mirror.normalasm.common.crashes.IMinecraftExtender; 14 | 15 | @Mixin(IntegratedServer.class) 16 | public class IntegratedServerMixin { 17 | 18 | @Shadow @Final private Minecraft mc; 19 | 20 | /** 21 | * @reason Checks if an integrated server crash was scheduled for this tick by the client, if Alt + F3 + C was pressed. 22 | */ 23 | @Inject(method = "tick", at = @At("HEAD")) 24 | private void beforeTick(CallbackInfo ci) { 25 | if (((IMinecraftExtender) mc).shouldCrashIntegratedServerNextTick()) { 26 | throw new ReportedException(new CrashReport("Manually triggered server-side debug crash", new Throwable())); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/TileEntityMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.crash.CrashReportCategory; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | import net.minecraft.tileentity.TileEntity; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(TileEntity.class) 12 | public class TileEntityMixin { 13 | 14 | // "Block Entity" to stay consistent with vanilla strings 15 | @Inject(method = "addInfoToCrashReport", at = @At("TAIL")) 16 | private void onAddEntityCrashInfo(CrashReportCategory category, CallbackInfo ci) { 17 | category.addDetail("Block Entity NBT", () -> ((TileEntity) (Object) this).writeToNBT(new NBTTagCompound()).toString()); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/TileEntityRenderDispatcherMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Shadow; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | import mirror.normalasm.common.crashes.IStateful; 10 | 11 | @Mixin(TileEntityRendererDispatcher.class) 12 | public class TileEntityRenderDispatcherMixin implements IStateful { 13 | 14 | @Shadow private boolean drawingBatch; 15 | 16 | @Inject(method = "", at = @At(value = "RETURN")) 17 | public void onInit(CallbackInfo ci) { 18 | register(); 19 | } 20 | 21 | @Override 22 | public void resetState() { 23 | if (drawingBatch) { 24 | drawingBatch = false; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/crashes/mixins/UtilMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.crashes.mixins; 2 | 3 | import net.minecraft.crash.CrashReport; 4 | import net.minecraft.util.Util; 5 | import org.apache.logging.log4j.Logger; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Overwrite; 8 | import mirror.normalasm.common.crashes.CrashUtils; 9 | 10 | import javax.annotation.Nullable; 11 | import java.util.concurrent.ExecutionException; 12 | import java.util.concurrent.FutureTask; 13 | 14 | @Mixin(Util.class) 15 | public class UtilMixin { 16 | 17 | /** 18 | * @author VanillaFix 19 | * @reason Warn the player (configurable to crash or log too) instead of only logging a 20 | * message a scheduled task throws an exception. The default vanilla behaviour is dangerous 21 | * as things will fail silently, making future bugs much harder to solve. In fact, it may 22 | * actually be a vanilla bug that the client doesn't crash, since they are using the "fatal" 23 | * log level, which is otherwise used only for problems which crash the game. 24 | */ 25 | @Overwrite 26 | @Nullable 27 | // TODO: Utils shouldn't depend on minecraft, redirect individual calls to runTask instead 28 | public static V runTask(FutureTask task, Logger logger) { 29 | task.run(); 30 | try { 31 | return task.get(); 32 | } catch (InterruptedException | ExecutionException e) { 33 | CrashUtils.notify(new CrashReport("Error executing task", e)); 34 | return null; 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/devenv/mixins/FMLModContainerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.devenv.mixins; 2 | 3 | import net.minecraftforge.fml.common.FMLModContainer; 4 | import net.minecraftforge.fml.common.MetadataCollection; 5 | import net.minecraftforge.fml.common.ModMetadata; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(value = FMLModContainer.class, remap = false) 13 | public class FMLModContainerMixin { 14 | 15 | @Shadow private ModMetadata modMetadata; 16 | 17 | @Inject(method = "bindMetadata", at = @At("RETURN")) 18 | private void voidForgeRequirements(MetadataCollection mc, CallbackInfo ci) { 19 | if (modMetadata.requiredMods != null) { 20 | modMetadata.requiredMods.removeIf(av -> av.getLabel().equals("forge")); 21 | } 22 | if (modMetadata.dependencies != null) { 23 | modMetadata.dependencies.removeIf(av -> av.getLabel().equals("forge")); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/efficienthashing/mixins/BlockPosMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.efficienthashing.mixins; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.util.math.Vec3i; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | 7 | /** 8 | * Thanks to 9 | * @author PrototypeTrousers: for bringing attention to this issue: https://i.imgur.com/RctqPTl.png 10 | * @author Baritone: for the hashCode implemntation. It beats out vanilla hashCode implementation especially when collisions occur (20%!) 11 | * 12 | * Do NOT target Vec3i, worst mistake of my LIFE. 13 | */ 14 | @Mixin(BlockPos.class) 15 | public abstract class BlockPosMixin extends Vec3i { 16 | 17 | protected BlockPosMixin(int x, int y, int z) { 18 | super(x, y, z); 19 | throw new AssertionError(); 20 | } 21 | 22 | @Override 23 | public int hashCode() { 24 | long hash = 3241L; 25 | hash = 3457689L * hash + getX(); 26 | hash = 8734625L * hash + getY(); 27 | return (int) (2873465L * hash + getZ()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/forgefixes/mixins/ChunkMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.forgefixes.mixins; 2 | 3 | import net.minecraft.tileentity.TileEntity; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.chunk.Chunk; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.Map; 13 | 14 | @Mixin(Chunk.class) 15 | public class ChunkMixin { 16 | 17 | @Redirect(method = "onLoad", at = @At(value = "INVOKE", target = "Ljava/util/Map;values()Ljava/util/Collection;", remap = false)) 18 | private Collection copiedValues(Map map) { 19 | return new ArrayList<>(map.values()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/forgefixes/mixins/DimensionTypeMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.forgefixes.mixins; 2 | 3 | import net.minecraft.world.DimensionType; 4 | import net.minecraft.world.WorldProvider; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 9 | 10 | @Mixin(DimensionType.class) 11 | public class DimensionTypeMixin { 12 | 13 | private static DimensionType[] normalRealValues = new DimensionType[] { DimensionType.OVERWORLD, DimensionType.NETHER, DimensionType.THE_END }; 14 | 15 | @Inject(method = "register", at = @At("TAIL"), remap = false) 16 | private static void storeRegDimension(String name, String suffix, int id, Class provider, boolean keepLoaded, CallbackInfoReturnable cir) { 17 | DimensionType dim = cir.getReturnValue(); 18 | DimensionType[] newArray = new DimensionType[normalRealValues.length + 1]; 19 | int i; 20 | for (i = 0; i < normalRealValues.length; i++) { 21 | newArray[i] = normalRealValues[i]; 22 | } 23 | newArray[i] = dim; 24 | normalRealValues = newArray; 25 | } 26 | 27 | @Inject(method = "values", at = @At("HEAD"), cancellable = true, remap = false) 28 | private static void getValues(CallbackInfoReturnable cir) { 29 | cir.setReturnValue(normalRealValues); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/forgefixes/mixins/ForgeEventFactoryMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.forgefixes.mixins; 2 | 3 | import net.minecraftforge.event.ForgeEventFactory; 4 | import net.minecraftforge.event.entity.player.FillBucketEvent; 5 | import net.minecraftforge.fml.common.eventhandler.Event; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | 10 | @Mixin(value = ForgeEventFactory.class, remap = false) 11 | public class ForgeEventFactoryMixin { 12 | 13 | @SuppressWarnings("ConstantConditions") 14 | @Redirect(method = "onBucketUse", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/entity/player/FillBucketEvent;getResult()Lnet/minecraftforge/fml/common/eventhandler/Event$Result;")) 15 | private static Event.Result checkContract(FillBucketEvent event) { 16 | if (event.getResult() == Event.Result.ALLOW && event.getFilledBucket() == null) { 17 | return Event.Result.DEFAULT; 18 | } 19 | return event.getResult(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/internal/mixins/CapabilityDispatcherMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.internal.mixins; 2 | 3 | import net.minecraft.nbt.NBTBase; 4 | import net.minecraft.util.EnumFacing; 5 | import net.minecraftforge.common.capabilities.Capability; 6 | import net.minecraftforge.common.capabilities.CapabilityDispatcher; 7 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 8 | import net.minecraftforge.common.util.INBTSerializable; 9 | import org.apache.commons.lang3.ArrayUtils; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import mirror.normalasm.NormalLogger; 13 | import mirror.normalasm.api.ICapabilityDispatcherManipulator; 14 | 15 | import javax.annotation.Nullable; 16 | import java.util.Arrays; 17 | 18 | @Mixin(value = CapabilityDispatcher.class, remap = false) 19 | public class CapabilityDispatcherMixin implements ICapabilityDispatcherManipulator { 20 | 21 | @Shadow private ICapabilityProvider[] caps; 22 | @Shadow private INBTSerializable[] writers; 23 | @Shadow private String[] names; 24 | 25 | @Override 26 | public void injectCapability(String name, ICapabilityProvider provider) { 27 | this.caps = ArrayUtils.add(this.caps, provider); 28 | if (provider instanceof INBTSerializable) { 29 | this.writers = ArrayUtils.add(this.writers, (INBTSerializable) provider); 30 | this.names = ArrayUtils.add(this.names, name); 31 | } 32 | } 33 | 34 | @Override 35 | public void stripCapability(String name, Capability capability, @Nullable EnumFacing facing, T capabilityInstance) { 36 | ICapabilityProvider provider = null; 37 | for (ICapabilityProvider p : this.caps) { 38 | if (p.getCapability(capability, facing) == capabilityInstance) { 39 | provider = p; 40 | } 41 | } 42 | if (provider == null) { 43 | NormalLogger.instance.error("{}@{} does not exist in {}", name, capability.getName(), Arrays.toString(this.caps)); 44 | return; 45 | } 46 | this.caps = ArrayUtils.removeElement(this.caps, provider); 47 | if (provider instanceof INBTSerializable) { 48 | this.writers = ArrayUtils.removeElement(this.writers, provider); 49 | this.names = ArrayUtils.removeElement(this.names, name); 50 | } 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/internal/mixins/ItemStackMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.internal.mixins; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraft.util.ResourceLocation; 6 | import net.minecraftforge.common.capabilities.CapabilityDispatcher; 7 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import mirror.normalasm.api.IItemStackCapabilityInjector; 11 | import mirror.normalasm.api.ICapabilityDispatcherManipulator; 12 | 13 | import java.util.Collections; 14 | 15 | @Mixin(value = ItemStack.class, remap = false) 16 | public abstract class ItemStackMixin implements IItemStackCapabilityInjector { 17 | 18 | @Shadow private CapabilityDispatcher capabilities; 19 | 20 | @Override 21 | public CapabilityDispatcher getDispatcher() { 22 | return this.capabilities == null ? this.capabilities = new CapabilityDispatcher(Collections.emptyMap(), null) : this.capabilities; 23 | } 24 | 25 | @Override 26 | public CapabilityDispatcher initDispatcher(ResourceLocation capabilityKey, ICapabilityProvider provider) { 27 | if (this.capabilities == null) { 28 | return this.capabilities = new CapabilityDispatcher(ImmutableMap.of(capabilityKey, provider), null); 29 | } 30 | ((ICapabilityDispatcherManipulator) (Object) this.capabilities).injectCapability(capabilityKey, provider); 31 | return this.capabilities; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/internal/mixins/TextureManagerAccessor.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.internal.mixins; 2 | 3 | import net.minecraft.client.renderer.texture.ITextureObject; 4 | import net.minecraft.client.renderer.texture.TextureManager; 5 | import net.minecraft.util.ResourceLocation; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.gen.Accessor; 8 | 9 | import java.util.Map; 10 | 11 | @Mixin(TextureManager.class) 12 | public interface TextureManagerAccessor { 13 | 14 | @Accessor 15 | Map getMapTextureObjects(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/internal/mixins/TileEntityMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.internal.mixins; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | import net.minecraft.tileentity.TileEntity; 5 | import net.minecraftforge.fml.relauncher.Side; 6 | import net.minecraftforge.fml.relauncher.SideOnly; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.At.Shift; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | import mirror.normalasm.NormalASM; 14 | 15 | @SideOnly(Side.CLIENT) 16 | @Mixin(TileEntity.class) 17 | public class TileEntityMixin { 18 | 19 | @Shadow(remap = false) private NBTTagCompound customTileData; 20 | 21 | @Inject(method = "readFromNBT", 22 | at = @At(value = "INVOKE_ASSIGN", 23 | target = "Lnet/minecraft/nbt/NBTTagCompound;getCompoundTag(Ljava/lang/String;)Lnet/minecraft/nbt/NBTTagCompound;", 24 | ordinal = 0, 25 | shift = Shift.AFTER, 26 | by = 2)) 27 | private void afterReadingFromNBT(NBTTagCompound compound, CallbackInfo ci) { 28 | if (NormalASM.customTileDataConsumer != null) { 29 | NormalASM.customTileDataConsumer.accept((TileEntity) (Object) this, customTileData); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/java/JavaFixes.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.java; 2 | 3 | import com.google.common.base.Stopwatch; 4 | import mirror.normalasm.api.NormalStringPool; 5 | import net.minecraft.launchwrapper.Launch; 6 | import net.minecraftforge.event.world.WorldEvent; 7 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 8 | import mirror.normalasm.NormalLogger; 9 | import mirror.normalasm.NormalReflector; 10 | 11 | import java.lang.invoke.MethodHandle; 12 | import java.security.*; 13 | import java.util.ConcurrentModificationException; 14 | import java.util.Enumeration; 15 | import java.util.HashMap; 16 | 17 | @SuppressWarnings("all") 18 | public class JavaFixes { 19 | 20 | private static final MethodHandle SECURECLASSLOADER$PDCACHE$GETTER; 21 | private static final MethodHandle PERMISSION$NAME$SETTER; 22 | 23 | static { 24 | MethodHandle secureClassLoader$pdcache$getter = null; 25 | MethodHandle permission$name$setter = null; 26 | try { 27 | secureClassLoader$pdcache$getter = NormalReflector.resolveFieldGetter(SecureClassLoader.class, "pdcache"); 28 | permission$name$setter = NormalReflector.resolveFieldSetter(Permission.class, "name"); 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | SECURECLASSLOADER$PDCACHE$GETTER = secureClassLoader$pdcache$getter; 33 | PERMISSION$NAME$SETTER = permission$name$setter; 34 | } 35 | 36 | public static final JavaFixes INSTANCE = new JavaFixes(); 37 | 38 | private JavaFixes() { 39 | run(); 40 | } 41 | 42 | 43 | private void run() { 44 | Stopwatch stopwatch = Stopwatch.createStarted(); 45 | try { 46 | NormalStringPool.establishPool(NormalStringPool.FILE_PERMISSIONS_ID, 512); 47 | HashMap pdcache = (HashMap) SECURECLASSLOADER$PDCACHE$GETTER.invoke(Launch.classLoader); 48 | for (ProtectionDomain pd : pdcache.values()) { 49 | PermissionCollection pc = pd.getPermissions(); 50 | if (pc != null) { 51 | Enumeration perms = pc.elements(); 52 | while (perms.hasMoreElements()) { 53 | Permission perm = perms.nextElement(); 54 | PERMISSION$NAME$SETTER.invokeExact(perm, NormalStringPool.canonicalize(perm.getName())); 55 | } 56 | } 57 | } 58 | NormalStringPool.purgePool(NormalStringPool.FILE_PERMISSIONS_ID); 59 | } 60 | catch (ConcurrentModificationException ignored) { } // Swallow it, we don't care enough about the CME here 61 | catch (Throwable t) { 62 | t.printStackTrace(); 63 | } 64 | NormalLogger.instance.info("Took {} to canonicalize Java's FilePermission caches.", stopwatch.stop()); 65 | } 66 | 67 | @SubscribeEvent 68 | public void onWorldLoad(WorldEvent.Load event) { 69 | run(); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/lockcode/mixins/LockCodeMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.lockcode.mixins; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | import net.minecraft.world.LockCode; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Overwrite; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | 10 | /** 11 | * Fixes LockCode not using its EMPTY variant when loading the EMPTY one from nbt 12 | */ 13 | @Mixin(LockCode.class) 14 | public class LockCodeMixin { 15 | 16 | @Shadow @Final public static LockCode EMPTY_CODE; 17 | 18 | /** 19 | * @author Rongmario 20 | * @reason Use EMPTY_CODE if Lock string isEmpty, which happens every time a tile that uses this is loaded from nbt 21 | */ 22 | @Overwrite 23 | public static LockCode fromNBT(NBTTagCompound nbt) { 24 | if (nbt.hasKey("Lock", 8)) { 25 | String s = nbt.getString("Lock"); 26 | return s.isEmpty() ? EMPTY_CODE : new LockCode(s); 27 | } else { 28 | return EMPTY_CODE; 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/mcfixes/mixins/mc129057/InventoryPlayerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.mcfixes.mixins.mc129057; 2 | 3 | import net.minecraft.entity.player.InventoryPlayer; 4 | import net.minecraft.item.ItemStack; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Redirect; 8 | 9 | @Mixin(InventoryPlayer.class) 10 | public class InventoryPlayerMixin { 11 | 12 | /** 13 | * Compare items by item type and meta rather than NBT when looking for items for the 14 | * crafting recipe. Note that the item is still checked (in findSlotMatchingUnusedItem) 15 | * to make sure it is not enchanted or renamed. If the recipe item has meta 32767, any 16 | * item meta is accepted (see Ingredient.apply). 17 | *

18 | * Bugs fixed: 19 | * - https://bugs.mojang.com/browse/MC-129057 20 | */ 21 | @Redirect(method = "findSlotMatchingUnusedItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/InventoryPlayer;stackEqualExact(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z")) 22 | private boolean stackEqualExact(InventoryPlayer inventoryPlayer, ItemStack stack1, ItemStack stack2) { 23 | return stack1.getItem() == stack2.getItem() && (stack1.getMetadata() == 32767 || stack1.getMetadata() == stack2.getMetadata()); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/mcfixes/mixins/mc129556/MinecraftMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.mcfixes.mixins.mc129556; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.texture.TextureManager; 5 | import net.minecraft.profiler.Profiler; 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Redirect; 11 | 12 | @Mixin(Minecraft.class) 13 | public class MinecraftMixin { 14 | 15 | @Shadow @Final public Profiler profiler; 16 | 17 | /** @reason Fix GUI logic being included as part of "root.tick.textures" (https://bugs.mojang.com/browse/MC-129556) */ 18 | @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V", ordinal = 0)) 19 | private void endStartGUISection(Profiler profiler, String name) { 20 | profiler.endStartSection("gui"); 21 | } 22 | 23 | /** @reason Part 2 of GUI logic fix. */ 24 | @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/TextureManager;tick()V", ordinal = 0)) 25 | private void tickTextureManagerWithCorrectProfiler(TextureManager textureManager) { 26 | profiler.endStartSection("textures"); 27 | textureManager.tick(); 28 | profiler.endStartSection("gui"); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/mcfixes/mixins/mc2071/EntityPlayerSPMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.mcfixes.mixins.mc2071; 2 | 3 | import net.minecraft.client.entity.EntityPlayerSP; 4 | import net.minecraft.client.gui.GuiScreen; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Redirect; 8 | 9 | // TODO: ditch mixin 10 | @Mixin(EntityPlayerSP.class) 11 | public class EntityPlayerSPMixin { 12 | 13 | /** 14 | * @reason Enables opening GUIs in nether portals. (see https://bugs.mojang.com/browse/MC-2071). This works by making minecraft think that GUI pauses the game. 15 | */ 16 | @Redirect(method = "onLivingUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiScreen;doesGuiPauseGame()Z")) 17 | private boolean onPauseCheck(GuiScreen guiScreen) { 18 | return true; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/mcfixes/mixins/skindownloading/ThreadDownloadImageDataMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.mcfixes.mixins.skindownloading; 2 | 3 | import com.google.common.util.concurrent.ThreadFactoryBuilder; 4 | import net.minecraft.client.renderer.ThreadDownloadImageData; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Unique; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | 10 | import java.util.concurrent.Executor; 11 | import java.util.concurrent.Executors; 12 | 13 | @Mixin(ThreadDownloadImageData.class) 14 | public class ThreadDownloadImageDataMixin { 15 | 16 | @Unique private static final Executor EXECUTOR = Executors.newFixedThreadPool(Math.max(2, Runtime.getRuntime().availableProcessors() / 2), 17 | new ThreadFactoryBuilder() 18 | .setNameFormat("Skin Downloader #%d") 19 | .setDaemon(true) 20 | .setPriority(Thread.MIN_PRIORITY) 21 | .build()); 22 | 23 | @Redirect(method = "loadTextureFromServer", at = @At(value = "INVOKE", target = "Ljava/lang/Thread;start()V", remap = false)) 24 | private void onThreadStart(Thread thread) { 25 | EXECUTOR.execute(thread); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/misc_fluidregistry/mixins/FluidRegistryMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.misc_fluidregistry.mixins; 2 | 3 | import net.minecraftforge.fluids.FluidRegistry; 4 | import net.minecraftforge.fml.common.FMLLog; 5 | import net.minecraftforge.fml.common.Loader; 6 | import net.minecraftforge.fml.common.LoaderState; 7 | import net.minecraftforge.fml.common.ModContainer; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Overwrite; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | @Mixin(value = FluidRegistry.class, remap = false) 13 | public class FluidRegistryMixin { 14 | 15 | @Shadow static boolean universalBucketEnabled; 16 | 17 | /** 18 | * @author Rongmario 19 | * @reason Disables the hasReachedState check if {@link FluidRegistryMixin#universalBucketEnabled} is already true 20 | */ 21 | @Overwrite 22 | public static void enableUniversalBucket() { 23 | if (universalBucketEnabled) { 24 | return; 25 | } 26 | if (Loader.instance().hasReachedState(LoaderState.PREINITIALIZATION)) { 27 | ModContainer modContainer = Loader.instance().activeModContainer(); 28 | String modContainerName = modContainer == null ? null : modContainer.getName(); 29 | FMLLog.log.error("Trying to activate the universal filled bucket too late. Call it statically in your Mods class. Mod: {}", modContainerName); 30 | } else { 31 | universalBucketEnabled = true; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/astralsorcery/mixins/EnchantmentUpgradeHelperInvoker.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.astralsorcery.mixins; 2 | 3 | import hellfirepvp.astralsorcery.common.enchantment.amulet.EnchantmentUpgradeHelper; 4 | import net.minecraft.item.ItemStack; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Invoker; 7 | 8 | @Mixin(EnchantmentUpgradeHelper.class) 9 | public interface EnchantmentUpgradeHelperInvoker { 10 | 11 | @Invoker(value = "removeAmuletOwner", remap = false) 12 | static void normalasm$removeAmuletOwner(ItemStack stack) { throw new AssertionError(); } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/astralsorcery/mixins/ItemEnchantmentAmuletMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.astralsorcery.mixins; 2 | 3 | import baubles.api.IBauble; 4 | import hellfirepvp.astralsorcery.common.enchantment.amulet.EnchantmentUpgradeHelper; 5 | import hellfirepvp.astralsorcery.common.item.wearable.ItemEnchantmentAmulet; 6 | import net.minecraft.entity.EntityLivingBase; 7 | import net.minecraft.entity.player.EntityPlayer; 8 | import net.minecraft.init.SoundEvents; 9 | import net.minecraft.item.Item; 10 | import net.minecraft.item.ItemEnchantedBook; 11 | import net.minecraft.item.ItemPotion; 12 | import net.minecraft.item.ItemStack; 13 | import org.spongepowered.asm.mixin.Mixin; 14 | 15 | @Mixin(ItemEnchantmentAmulet.class) 16 | public abstract class ItemEnchantmentAmuletMixin implements IBauble { 17 | 18 | private static boolean isItemBlacklisted(ItemStack stack) { 19 | if (stack.isEmpty() || stack.getItemDamage() == Short.MAX_VALUE || stack.getMaxStackSize() > 1) { 20 | return true; 21 | } 22 | Item item = stack.getItem(); 23 | if (!(item instanceof ItemPotion) && !(item instanceof ItemEnchantedBook)) { 24 | return item.getRegistryName().getNamespace().equals("draconicevolution"); 25 | } 26 | return true; 27 | } 28 | 29 | @Override 30 | public void onWornTick(ItemStack stack, EntityLivingBase entityLivingBase) { 31 | EntityPlayer player = (EntityPlayer) entityLivingBase; 32 | for (ItemStack armorStack : player.getArmorInventoryList()) { 33 | if (!isItemBlacklisted(armorStack)) { 34 | EnchantmentUpgradeHelper.applyAmuletOwner(armorStack, player); 35 | } 36 | } 37 | ItemStack handStack = player.getHeldItemMainhand(); 38 | if (!isItemBlacklisted(handStack)) { 39 | EnchantmentUpgradeHelper.applyAmuletOwner(handStack, player); 40 | } 41 | handStack = player.getHeldItemOffhand(); 42 | if (!isItemBlacklisted(handStack)) { 43 | EnchantmentUpgradeHelper.applyAmuletOwner(handStack, player); 44 | } 45 | } 46 | 47 | // Doesn't take into account on player death: see PlayerAmuletHandlerMixin 48 | @Override 49 | public void onUnequipped(ItemStack stack, EntityLivingBase player) { 50 | player.playSound(SoundEvents.BLOCK_GLASS_PLACE, 0.65F, 6.4F); 51 | for (ItemStack armorStack : player.getArmorInventoryList()) { 52 | EnchantmentUpgradeHelperInvoker.normalasm$removeAmuletOwner(armorStack); 53 | } 54 | EnchantmentUpgradeHelperInvoker.normalasm$removeAmuletOwner(player.getHeldItemMainhand()); 55 | EnchantmentUpgradeHelperInvoker.normalasm$removeAmuletOwner(player.getHeldItemOffhand()); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/astralsorcery/mixins/PlayerAmuletHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.astralsorcery.mixins; 2 | 3 | import hellfirepvp.astralsorcery.common.auxiliary.tick.ITickHandler; 4 | import hellfirepvp.astralsorcery.common.enchantment.EnchantmentPlayerWornTick; 5 | import hellfirepvp.astralsorcery.common.enchantment.amulet.PlayerAmuletHandler; 6 | import hellfirepvp.astralsorcery.common.registry.RegistryEnchantments; 7 | import net.minecraft.enchantment.EnchantmentHelper; 8 | import net.minecraft.entity.player.EntityPlayer; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraftforge.event.entity.player.PlayerDropsEvent; 11 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 12 | import net.minecraftforge.fml.common.gameevent.TickEvent; 13 | import org.spongepowered.asm.mixin.Mixin; 14 | 15 | @Mixin(PlayerAmuletHandler.class) 16 | public abstract class PlayerAmuletHandlerMixin implements ITickHandler { 17 | 18 | @SubscribeEvent 19 | public void onPlayerDeath(PlayerDropsEvent event) { 20 | EntityPlayer player = event.getEntityPlayer(); 21 | for (ItemStack armorStack : player.getArmorInventoryList()) { 22 | EnchantmentUpgradeHelperInvoker.normalasm$removeAmuletOwner(armorStack); 23 | } 24 | EnchantmentUpgradeHelperInvoker.normalasm$removeAmuletOwner(player.getHeldItemMainhand()); 25 | EnchantmentUpgradeHelperInvoker.normalasm$removeAmuletOwner(player.getHeldItemOffhand()); 26 | } 27 | 28 | @Override 29 | public void tick(TickEvent.Type type, Object... context) { 30 | EntityPlayer player = (EntityPlayer) context[0]; 31 | for (EnchantmentPlayerWornTick enchant : RegistryEnchantments.wearableTickEnchantments) { 32 | int max = EnchantmentHelper.getMaxEnchantmentLevel(enchant, player); 33 | if (max > 0) { 34 | enchant.onWornTick(type == TickEvent.Type.CLIENT, player, max); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/b3m/CapitalizedNamespaceResourceLocation.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.b3m; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | 5 | import java.util.Locale; 6 | 7 | public class CapitalizedNamespaceResourceLocation extends ResourceLocation { 8 | 9 | public CapitalizedNamespaceResourceLocation(String namespaceIn, String pathIn) { 10 | super(namespaceIn, pathIn); 11 | } 12 | 13 | @Override 14 | public String getNamespace() { 15 | return super.getNamespace().toUpperCase(Locale.ROOT); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/b3m/mixins/B3M_CoreMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.b3m.mixins; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | import org.spongepowered.asm.mixin.Final; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Mutable; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | import sedridor.B3M.B3M_Core; 9 | import mirror.normalasm.common.modfixes.b3m.CapitalizedNamespaceResourceLocation; 10 | 11 | @Mixin(value = B3M_Core.class, remap = false) 12 | public class B3M_CoreMixin { 13 | 14 | @Shadow @Final @Mutable private static final ResourceLocation newMoonPhasesPng = new CapitalizedNamespaceResourceLocation("B3M", "textures/moon_phases.png"); 15 | @Shadow @Final @Mutable private static final ResourceLocation newSunPng = new CapitalizedNamespaceResourceLocation("B3M", "textures/sun.png"); 16 | @Shadow @Final @Mutable private static final ResourceLocation newMoonPhases2Png = new CapitalizedNamespaceResourceLocation("B3M", "textures/moon_phases2.png"); 17 | @Shadow @Final @Mutable private static final ResourceLocation newSun2Png = new CapitalizedNamespaceResourceLocation("B3M", "textures/sun2.png"); 18 | @Shadow @Final @Mutable private static final ResourceLocation newMoonPhasesBlank = new CapitalizedNamespaceResourceLocation("B3M", "textures/moon_phases_blank.png"); 19 | @Shadow @Final @Mutable private static final ResourceLocation newSunBlank = new CapitalizedNamespaceResourceLocation("B3M", "textures/sun_blank.png"); 20 | @Shadow @Final @Mutable private static final ResourceLocation[] newClouds = new CapitalizedNamespaceResourceLocation[] { 21 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_0.png"), 22 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_1.png"), 23 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_2.png"), 24 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_3.png"), 25 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_4.png"), 26 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_5.png"), 27 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_6.png"), 28 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_7.png"), 29 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_8.png"), 30 | new CapitalizedNamespaceResourceLocation("B3M", "textures/clouds_9.png") 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/ebwizardry/ArcaneLocks.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.ebwizardry; 2 | 3 | import electroblob.wizardry.spell.ArcaneLock; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | import net.minecraft.tileentity.TileEntity; 6 | 7 | import java.util.Collections; 8 | import java.util.Set; 9 | import java.util.WeakHashMap; 10 | import java.util.function.BiConsumer; 11 | 12 | public class ArcaneLocks { 13 | 14 | public static final Set ARCANE_LOCKED_TILES; 15 | public static final BiConsumer TRACK_ARCANE_TILES; 16 | 17 | static { 18 | ARCANE_LOCKED_TILES = Collections.newSetFromMap(new WeakHashMap<>()); 19 | TRACK_ARCANE_TILES = (tile, tag) -> { 20 | if (tag.hasUniqueId(ArcaneLock.NBT_KEY)) { 21 | ARCANE_LOCKED_TILES.add(tile); 22 | } 23 | ARCANE_LOCKED_TILES.remove(tile); 24 | }; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/evilcraftcompat/mixins/EnderIORecipeManagerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.evilcraftcompat.mixins; 2 | 3 | import crazypants.enderio.base.recipe.*; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Pseudo; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Redirect; 8 | 9 | @Pseudo 10 | @Mixin(targets = "org.cyclops.evilcraftcompat.modcompat.enderio.EnderIORecipeManager", remap = false) 11 | public class EnderIORecipeManagerMixin { 12 | 13 | @SuppressWarnings("all") 14 | @Redirect(method = "register", at = @At(value = "NEW", target = "crazypants/enderio/base/recipe/Recipe")) 15 | private static Recipe resolveCorrectRecipeSignature(IRecipeInput recipeInput, int energyRequired, RecipeBonusType bonusType, RecipeOutput... output) { 16 | return new Recipe(recipeInput, energyRequired, bonusType, RecipeLevel.IGNORE, output); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/immersiveengineering/mixins/BlockIEBaseMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.immersiveengineering.mixins; 2 | 3 | import blusunrize.immersiveengineering.common.blocks.BlockIEBase; 4 | import net.minecraft.block.material.EnumPushReaction; 5 | import net.minecraft.block.state.IBlockState; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Overwrite; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | 10 | @Mixin(BlockIEBase.class) 11 | public abstract class BlockIEBaseMixin { 12 | 13 | @Shadow public abstract int getMetaFromState(IBlockState state); 14 | @Shadow(remap = false) protected EnumPushReaction[] metaMobilityFlags; 15 | 16 | /** 17 | * @author Rongmario 18 | * @reason Fixes ArrayIndexOutOfBoundsException 19 | */ 20 | @Overwrite 21 | public EnumPushReaction getPushReaction(IBlockState state) { 22 | int meta = getMetaFromState(state); 23 | if (metaMobilityFlags.length <= meta || metaMobilityFlags[meta] == null) { 24 | return EnumPushReaction.NORMAL; 25 | } 26 | return metaMobilityFlags[meta]; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/qmd/QMDEventHandler.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.qmd; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.entity.RenderManager; 5 | import net.minecraft.entity.Entity; 6 | import net.minecraftforge.client.event.RenderWorldLastEvent; 7 | import net.minecraftforge.event.entity.EntityJoinWorldEvent; 8 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 9 | import mirror.normalasm.NormalReflector; 10 | 11 | import java.lang.ref.WeakReference; 12 | import java.util.ArrayList; 13 | import java.util.Iterator; 14 | import java.util.List; 15 | 16 | public class QMDEventHandler { 17 | 18 | private static final List> beamsInWorld = new ArrayList<>(1); 19 | private static final Class projectileClass = NormalReflector.getClass("lach_01298.qmd.entity.EntityBeamProjectile").get(); 20 | 21 | @SubscribeEvent 22 | public static void onBeamSpawn(EntityJoinWorldEvent event) { 23 | if (projectileClass.isInstance(event.getEntity())) { 24 | beamsInWorld.add(new WeakReference<>(event.getEntity())); 25 | } 26 | } 27 | 28 | @SubscribeEvent 29 | public static void onRenderWorldLast(RenderWorldLastEvent event) { 30 | if (beamsInWorld.isEmpty()) { 31 | return; 32 | } 33 | Iterator> iterator = beamsInWorld.listIterator(); 34 | float partialTicks = event.getPartialTicks(); 35 | double bx = 0D, by = 0D, bz = 0D, rx = 0D, ry = 0D, rz = 0D; 36 | float br = 0F; 37 | boolean calculated = false; 38 | while (iterator.hasNext()) { 39 | Entity entity = iterator.next().get(); 40 | if (entity == null || entity.isDead) { 41 | iterator.remove(); 42 | } else { 43 | RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); 44 | Entity renderEntity = renderManager.renderViewEntity; 45 | if (renderEntity.getDistanceSq(entity) <= (128 * 128)) { 46 | if (!calculated) { 47 | bx = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * (double) partialTicks; 48 | by = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * (double) partialTicks; 49 | bz = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * (double) partialTicks; 50 | br = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks; 51 | rx = renderEntity.lastTickPosX + (renderEntity.posX - renderEntity.lastTickPosX) * (double) partialTicks; 52 | ry = renderEntity.lastTickPosY + (renderEntity.posY - renderEntity.lastTickPosY) * (double) partialTicks; 53 | rz = renderEntity.lastTickPosZ + (renderEntity.posZ - renderEntity.lastTickPosZ) * (double) partialTicks; 54 | calculated = true; 55 | } 56 | renderManager.getEntityClassRenderObject(entity.getClass()).doRender(entity, bx - rx, by - ry, bz - rz, br, partialTicks); 57 | } 58 | } 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/xu2/TileCrafterExtension.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.xu2; 2 | 3 | import net.minecraftforge.fml.relauncher.Side; 4 | import net.minecraftforge.fml.relauncher.SideOnly; 5 | 6 | public interface TileCrafterExtension { 7 | 8 | @SideOnly(Side.CLIENT) 9 | void renderAlt(double x, double y, double z); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/modfixes/xu2/mixins/XUTESRBaseMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.modfixes.xu2.mixins; 2 | 3 | import com.rwtema.extrautils2.compatibility.CompatClientHelper; 4 | import com.rwtema.extrautils2.compatibility.TESRCompat; 5 | import com.rwtema.extrautils2.render.IVertexBuffer; 6 | import com.rwtema.extrautils2.tile.TileCrafter; 7 | import com.rwtema.extrautils2.tile.XUTile; 8 | import com.rwtema.extrautils2.tile.tesr.XUTESRBase; 9 | import net.minecraft.client.Minecraft; 10 | import net.minecraft.client.renderer.GlStateManager; 11 | import net.minecraft.client.renderer.RenderHelper; 12 | import net.minecraft.client.renderer.Tessellator; 13 | import net.minecraft.client.renderer.texture.TextureMap; 14 | import net.minecraft.client.renderer.vertex.VertexFormat; 15 | import net.minecraftforge.fml.relauncher.Side; 16 | import net.minecraftforge.fml.relauncher.SideOnly; 17 | import org.lwjgl.opengl.GL11; 18 | import org.spongepowered.asm.mixin.Mixin; 19 | import org.spongepowered.asm.mixin.Shadow; 20 | import mirror.normalasm.common.modfixes.xu2.TileCrafterExtension; 21 | import mirror.normalasm.config.NormalConfig; 22 | 23 | import javax.annotation.Nonnull; 24 | 25 | @Mixin(value = XUTESRBase.class, remap = false) 26 | public abstract class XUTESRBaseMixin extends TESRCompat { 27 | 28 | @Shadow public abstract void preRender(T te, int destroyStage); 29 | @Shadow public abstract void postRender(T te, int destroyStage); 30 | @Shadow public abstract void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage, IVertexBuffer renderer); 31 | 32 | @Shadow protected abstract int getDrawMode(T te); 33 | @Shadow protected abstract VertexFormat getVertexFormat(T te); 34 | 35 | @Override 36 | @SideOnly(Side.CLIENT) 37 | public void render(@Nonnull T te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) { 38 | if (NormalConfig.instance.fixXU2CrafterCrash && te instanceof TileCrafter) { 39 | ((TileCrafterExtension) te).renderAlt(x, y, z); 40 | } else { 41 | Tessellator tessellator = Tessellator.getInstance(); 42 | IVertexBuffer vertexBuffer = CompatClientHelper.wrap(tessellator.getBuffer()); 43 | this.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); 44 | RenderHelper.disableStandardItemLighting(); 45 | GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 46 | GlStateManager.enableBlend(); 47 | GlStateManager.disableCull(); 48 | 49 | if (Minecraft.isAmbientOcclusionEnabled()) { 50 | GlStateManager.shadeModel(GL11.GL_SMOOTH); 51 | } else { 52 | GlStateManager.shadeModel(GL11.GL_FLAT); 53 | } 54 | 55 | 56 | preRender(te, destroyStage); 57 | vertexBuffer.begin(getDrawMode(te), getVertexFormat(te)); 58 | renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, vertexBuffer); 59 | vertexBuffer.setTranslation(0, 0, 0); 60 | tessellator.draw(); 61 | postRender(te, destroyStage); 62 | RenderHelper.enableStandardItemLighting(); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/recipes/mixins/FurnaceRecipesMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.recipes.mixins; 2 | 3 | import it.unimi.dsi.fastutil.objects.*; 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraft.item.crafting.FurnaceRecipes; 6 | import net.minecraftforge.fml.common.FMLLog; 7 | import org.spongepowered.asm.mixin.*; 8 | import mirror.normalasm.config.NormalConfig; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * FurnaceRecipes are only item/meta sensitive, hence a simple Strategy is used. 14 | * 15 | * getSmeltingResult/getSmeltingExperience is now only a hash lookup. 16 | * experienceList doesn't have its floats boxed now. 17 | */ 18 | @Mixin(FurnaceRecipes.class) 19 | public abstract class FurnaceRecipesMixin { 20 | 21 | @Shadow @Final private Map smeltingList; 22 | @Shadow @Final private Map experienceList; 23 | 24 | @Shadow protected abstract boolean compareItemStacks(ItemStack stack1, ItemStack stack2); 25 | 26 | /** 27 | * @author Rongmario 28 | * @reason Use Object2FloatMap#put 29 | */ 30 | @Overwrite 31 | public void addSmeltingRecipe(ItemStack input, ItemStack stack, float experience) { 32 | if (getSmeltingResult(input) != ItemStack.EMPTY) { 33 | FMLLog.log.info("Ignored smelting recipe with conflicting input: {} = {}", input, stack); return; 34 | } 35 | this.smeltingList.put(input, stack); 36 | if (NormalConfig.instance.furnaceExperienceMost) { 37 | float prevExperience = ((Object2FloatMap) experienceList).getFloat(stack); 38 | if (experience > prevExperience) { 39 | ((Object2FloatMap) experienceList).put(stack, experience); 40 | } 41 | } else if (NormalConfig.instance.furnaceExperienceVanilla) { 42 | this.experienceList.put(stack, experience); 43 | } else { 44 | this.experienceList.putIfAbsent(stack, experience); 45 | } 46 | } 47 | 48 | /** 49 | * @author Rongmario 50 | * @reason Efficient getSmeltingResult 51 | */ 52 | @Overwrite 53 | public ItemStack getSmeltingResult(ItemStack stack) { 54 | ItemStack result = this.smeltingList.get(stack); 55 | return result == null ? ItemStack.EMPTY : result; 56 | } 57 | 58 | /** 59 | * @author Rongmario 60 | * @reason Efficient getSmeltingExperience 61 | */ 62 | @Overwrite 63 | public float getSmeltingExperience(ItemStack stack) { 64 | float exp = stack.getItem().getSmeltingExperience(stack); 65 | if (exp == -1) { 66 | if (NormalConfig.instance.furnaceExperienceVanilla) { 67 | for (Map.Entry entry : this.experienceList.entrySet()) { 68 | if (this.compareItemStacks(stack, entry.getKey())) { 69 | return entry.getValue(); 70 | } 71 | } 72 | } else { 73 | return ((Object2FloatMap) this.experienceList).getFloat(stack); 74 | } 75 | } 76 | return exp; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/registries/mixins/RegistrySimpleMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.registries.mixins; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ReferenceArrayMap; 4 | import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; 5 | import net.minecraft.util.registry.RegistrySimple; 6 | import org.apache.commons.lang3.Validate; 7 | import org.apache.logging.log4j.Logger; 8 | import org.spongepowered.asm.mixin.*; 9 | import mirror.normalasm.NormalASM; 10 | import mirror.normalasm.api.mixins.RegistrySimpleExtender; 11 | 12 | import javax.annotation.Nullable; 13 | import java.util.Map; 14 | import java.util.Random; 15 | 16 | @Mixin(RegistrySimple.class) 17 | public class RegistrySimpleMixin implements RegistrySimpleExtender { 18 | 19 | @Shadow @Final private static Logger LOGGER; 20 | 21 | @Shadow @Mutable @Final protected Map registryObjects; 22 | 23 | /** 24 | * @author Rongmario 25 | * @reason Better map structure 26 | */ 27 | @Overwrite 28 | protected Map createUnderlyingMap() { 29 | if (NormalASM.simpleRegistryInstances != null) { 30 | NormalASM.simpleRegistryInstances.add(this); 31 | } 32 | return new Object2ReferenceOpenHashMap<>(); 33 | } 34 | 35 | /** 36 | * @author Rongmario 37 | * @reason Remove values reference 38 | */ 39 | @Overwrite 40 | public void putObject(K key, V value) { 41 | Validate.notNull(key); 42 | Validate.notNull(value); 43 | if (this.registryObjects.containsKey(key)) { 44 | LOGGER.debug("Adding duplicate key '{}' to registry", key); 45 | } 46 | this.registryObjects.put(key, value); 47 | } 48 | 49 | /** 50 | * @author Rongmario 51 | * @reason Remove values reference + use streams to gather a random object 52 | */ 53 | @Nullable 54 | @Overwrite 55 | public V getRandomObject(Random random) { 56 | return this.registryObjects.values().stream().skip(random.nextInt(this.registryObjects.size())).findFirst().get(); 57 | } 58 | 59 | @Override 60 | public void clearUnderlyingMap() { 61 | this.registryObjects.clear(); 62 | } 63 | 64 | @Override 65 | public void trim() { 66 | if (this.registryObjects instanceof Object2ReferenceOpenHashMap) { 67 | if (this.registryObjects.size() > 32) { 68 | ((Object2ReferenceOpenHashMap) this.registryObjects).trim(); 69 | } else { 70 | this.registryObjects = new Object2ReferenceArrayMap<>(this.registryObjects); 71 | } 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/registries/mixins/SoundRegistryMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.registries.mixins; 2 | 3 | import net.minecraft.client.audio.SoundEventAccessor; 4 | import net.minecraft.client.audio.SoundRegistry; 5 | import net.minecraft.util.ResourceLocation; 6 | import net.minecraft.util.registry.RegistrySimple; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import mirror.normalasm.api.mixins.RegistrySimpleExtender; 10 | 11 | import java.util.Map; 12 | 13 | @Mixin(SoundRegistry.class) 14 | public abstract class SoundRegistryMixin extends RegistrySimple implements RegistrySimpleExtender { 15 | 16 | /** 17 | * @author Rongmario 18 | * @reason Use RegistrySimple#createUnderlyingMap 19 | */ 20 | @Overwrite 21 | protected Map createUnderlyingMap() { 22 | return super.createUnderlyingMap(); 23 | } 24 | 25 | /** 26 | * @author Rongmario 27 | * @reason Use RegistrySimpleExtender#clearUnderlyingMap 28 | */ 29 | @Overwrite 30 | public void clearMap() { 31 | this.clearUnderlyingMap(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/IRefreshEvent.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents; 2 | 3 | import com.google.common.base.Preconditions; 4 | import net.minecraft.block.state.IBlockState; 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.util.EnumFacing; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.world.World; 9 | import net.minecraftforge.fml.common.eventhandler.Event; 10 | import net.minecraftforge.fml.common.eventhandler.EventPriority; 11 | import net.minecraftforge.fml.relauncher.Side; 12 | 13 | import java.util.EnumSet; 14 | 15 | /** 16 | * Events will gather this and use as their new values before firing on the EventBus 17 | * 18 | * All {@link net.minecraftforge.fml.common.eventhandler.Event} implementing this must: 19 | * 20 | * 1. Have a unique field: { private EventPriority normalPriority = null; } 21 | * 2. Override {@link Event#getPhase()} and {@link Event#setPhase(EventPriority)} 22 | * 3. Point normalPriority towards those getters/setters 23 | * 4. Check Preconditions in {@link Event#setPhase(EventPriority)} via {@link IRefreshEvent#checkPrecondition(EventPriority, EventPriority)} 24 | */ 25 | public interface IRefreshEvent { 26 | 27 | // TODO: evaluate if we need to check preconditions 28 | @Deprecated 29 | static void checkPrecondition(EventPriority current, EventPriority next) { 30 | Preconditions.checkNotNull(next, "setPhase argument must not be null"); 31 | Preconditions.checkArgument((current == null ? -1 : current.ordinal()) < next.ordinal(), "Attempted to set event phase to %s when already %s", next, current); 32 | } 33 | 34 | default void beforeAttachCapabilities(Object data) { 35 | 36 | } 37 | 38 | default void afterAttachCapabilities() { 39 | 40 | } 41 | 42 | default void beforeBlockEvent(World world, BlockPos pos, IBlockState state) { 43 | 44 | } 45 | 46 | default void afterBlockEvent() { 47 | 48 | } 49 | 50 | default void beforeNeighborNotify(EnumSet notifiedSides, boolean forceRedstoneUpdate) { 51 | 52 | } 53 | 54 | default void afterNeighborNotify() { 55 | 56 | } 57 | 58 | // Special-case for PlayerTickEvents 59 | default IRefreshEvent setTickSide(Side side) { 60 | return this; 61 | } 62 | 63 | default void beforeWorldTick(World world) { 64 | 65 | } 66 | 67 | default void afterWorldTick() { 68 | 69 | } 70 | 71 | default void beforePlayerTick(EntityPlayer player) { 72 | 73 | } 74 | 75 | default void afterPlayerTick() { 76 | 77 | } 78 | 79 | default void beforeRenderTick(float timer) { 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/blocks/BlockEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.blocks; 2 | 3 | import net.minecraft.block.state.IBlockState; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.World; 6 | import net.minecraftforge.event.world.BlockEvent; 7 | import net.minecraftforge.fml.common.eventhandler.Event; 8 | import org.spongepowered.asm.mixin.*; 9 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 10 | 11 | @Mixin(value = BlockEvent.class, remap = false) 12 | public class BlockEventMixin extends Event implements IRefreshEvent { 13 | 14 | @Shadow @Final @Mutable private World world; 15 | @Shadow @Final @Mutable private BlockPos pos; 16 | @Shadow @Final @Mutable private IBlockState state; 17 | 18 | @Override 19 | public void beforeBlockEvent(World world, BlockPos pos, IBlockState state) { 20 | this.world = world; 21 | this.pos = pos; 22 | this.state = state; 23 | } 24 | 25 | @Override 26 | public void afterBlockEvent() { 27 | this.world = null; 28 | this.pos = null; 29 | this.state = null; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/blocks/NeighborNotifyEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.blocks; 2 | 3 | import net.minecraft.util.EnumFacing; 4 | import net.minecraftforge.event.world.BlockEvent.NeighborNotifyEvent; 5 | import net.minecraftforge.fml.common.eventhandler.Event; 6 | import net.minecraftforge.fml.common.eventhandler.EventPriority; 7 | import org.spongepowered.asm.mixin.*; 8 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 9 | 10 | import javax.annotation.Nonnull; 11 | import javax.annotation.Nullable; 12 | import java.util.EnumSet; 13 | 14 | @Mixin(NeighborNotifyEvent.class) 15 | public class NeighborNotifyEventMixin extends Event implements IRefreshEvent { 16 | 17 | @Shadow @Final @Mutable private EnumSet notifiedSides; 18 | @Shadow @Final @Mutable private boolean forceRedstoneUpdate; 19 | 20 | @Unique private EventPriority normalPriority = null; 21 | 22 | @Override 23 | public void beforeNeighborNotify(EnumSet notifiedSides, boolean forceRedstoneUpdate) { 24 | this.notifiedSides = notifiedSides; 25 | this.forceRedstoneUpdate = forceRedstoneUpdate; 26 | } 27 | 28 | @Override 29 | public void afterNeighborNotify() { 30 | this.notifiedSides = null; 31 | } 32 | 33 | @Nullable 34 | @Override 35 | public EventPriority getPhase() { 36 | return normalPriority; 37 | } 38 | 39 | @Override 40 | public void setPhase(@Nonnull EventPriority next) { 41 | this.normalPriority = next; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/capabilities/AttachCapabilitiesEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.capabilities; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; 4 | import net.minecraft.util.ResourceLocation; 5 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 6 | import net.minecraftforge.event.AttachCapabilitiesEvent; 7 | import net.minecraftforge.fml.common.eventhandler.Event; 8 | import net.minecraftforge.fml.common.eventhandler.EventPriority; 9 | import org.spongepowered.asm.mixin.*; 10 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 11 | 12 | import javax.annotation.Nonnull; 13 | import javax.annotation.Nullable; 14 | import java.util.Map; 15 | 16 | @Mixin(value = AttachCapabilitiesEvent.class, remap = false) 17 | public class AttachCapabilitiesEventMixin extends Event implements IRefreshEvent { 18 | 19 | @Shadow @Final @Mutable private T obj; 20 | @Shadow @Final @Mutable private Map caps = new Object2ObjectArrayMap<>(1); 21 | 22 | @Unique private EventPriority normalPriority = null; 23 | 24 | @Override 25 | public void beforeAttachCapabilities(Object data) { 26 | this.obj = (T) data; 27 | } 28 | 29 | @Override 30 | public void afterAttachCapabilities() { 31 | this.obj = null; 32 | this.caps.clear(); 33 | this.normalPriority = null; 34 | } 35 | 36 | @Nullable 37 | @Override 38 | public EventPriority getPhase() { 39 | return normalPriority; 40 | } 41 | 42 | @Override 43 | public void setPhase(@Nonnull EventPriority next) { 44 | this.normalPriority = next; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/gameevent/PlayerTickEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.gameevent; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Mutable; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 10 | 11 | @Mixin(value = PlayerTickEvent.class, remap = true) 12 | public class PlayerTickEventMixin implements IRefreshEvent { 13 | 14 | @Shadow @Final @Mutable public EntityPlayer player; 15 | 16 | @Override 17 | public void beforePlayerTick(EntityPlayer player) { 18 | this.player = player; 19 | } 20 | 21 | @Override 22 | public void afterPlayerTick() { 23 | this.player = null; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/gameevent/RenderTickEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.gameevent; 2 | 3 | import net.minecraftforge.client.model.animation.Animation; 4 | import net.minecraftforge.fml.common.gameevent.TickEvent.RenderTickEvent; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Mutable; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 10 | 11 | @Mixin(RenderTickEvent.class) 12 | public class RenderTickEventMixin implements IRefreshEvent { 13 | 14 | @Shadow @Final @Mutable public float renderTickTime; 15 | 16 | @Override 17 | public void beforeRenderTick(float timer) { 18 | Animation.setClientPartialTickTime(timer); 19 | this.renderTickTime = timer; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/gameevent/TickEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.gameevent; 2 | 3 | import net.minecraftforge.fml.common.eventhandler.Event; 4 | import net.minecraftforge.fml.common.eventhandler.EventPriority; 5 | import net.minecraftforge.fml.common.gameevent.TickEvent; 6 | import net.minecraftforge.fml.relauncher.Side; 7 | import org.spongepowered.asm.mixin.*; 8 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 9 | 10 | import javax.annotation.Nonnull; 11 | import javax.annotation.Nullable; 12 | 13 | @Mixin(value = TickEvent.class, remap = false) 14 | public class TickEventMixin extends Event implements IRefreshEvent { 15 | 16 | @Shadow @Final @Mutable public Side side; 17 | 18 | @Unique private EventPriority normalPriority = null; 19 | 20 | @Override 21 | public IRefreshEvent setTickSide(Side side) { 22 | this.side = side; 23 | return this; 24 | } 25 | 26 | @Nullable 27 | @Override 28 | public EventPriority getPhase() { 29 | return normalPriority; 30 | } 31 | 32 | @Override 33 | public void setPhase(@Nonnull EventPriority next) { 34 | this.normalPriority = next; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/singletonevents/mixins/gameevent/WorldTickEventMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.singletonevents.mixins.gameevent; 2 | 3 | import net.minecraft.world.World; 4 | import net.minecraftforge.fml.common.gameevent.TickEvent.WorldTickEvent; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Mutable; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import mirror.normalasm.common.singletonevents.IRefreshEvent; 10 | 11 | @Mixin(value = WorldTickEvent.class, remap = false) 12 | public class WorldTickEventMixin implements IRefreshEvent { 13 | 14 | @Shadow @Final @Mutable public World world; 15 | 16 | @Override 17 | public void beforeWorldTick(World world) { 18 | this.world = world; 19 | } 20 | 21 | @Override 22 | public void afterWorldTick() { 23 | this.world = null; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/common/vanities/mixins/FMLCommonHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.common.vanities.mixins; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import net.minecraftforge.fml.common.FMLCommonHandler; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 10 | import mirror.normalasm.core.NormalLoadingPlugin; 11 | 12 | @Mixin(FMLCommonHandler.class) 13 | public class FMLCommonHandlerMixin { 14 | 15 | @Inject(method = "computeBranding", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList$Builder;add(Ljava/lang/Object;)Lcom/google/common/collect/ImmutableList$Builder;", ordinal = 2, remap = false), locals = LocalCapture.CAPTURE_FAILHARD, remap = false) 16 | private void injectNormalASMBranding(CallbackInfo ci, ImmutableList.Builder builder) { 17 | builder.add("NormalASM " + NormalLoadingPlugin.VERSION); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/config/annotation/Ignore.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.config.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Deprecated 9 | @Target(ElementType.FIELD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Ignore { } 12 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/config/annotation/Since.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.config.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Deprecated 9 | @Target(ElementType.FIELD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Since { 12 | 13 | String value(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/core/NormalLateMixinLoader.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import net.minecraftforge.fml.common.Loader; 5 | import mirror.normalasm.config.NormalConfig; 6 | import zone.rong.mixinbooter.ILateMixinLoader; 7 | 8 | import java.util.List; 9 | 10 | public class NormalLateMixinLoader implements ILateMixinLoader { 11 | 12 | @Override 13 | public List getMixinConfigs() { 14 | return Lists.newArrayList( 15 | "mixins.bakedquadsquasher.json", 16 | "mixins.modfixes_immersiveengineering.json", 17 | "mixins.modfixes_astralsorcery.json", 18 | "mixins.capability_astralsorcery.json", 19 | "mixins.modfixes_evilcraftcompat.json", 20 | "mixins.modfixes_ebwizardry.json", 21 | "mixins.modfixes_xu2.json", 22 | "mixins.modfixes_b3m.json", 23 | "mixins.searchtree_mod.json"); 24 | } 25 | 26 | @Override 27 | public boolean shouldMixinConfigQueue(String mixinConfig) { 28 | switch (mixinConfig) { 29 | case "mixins.bakedquadsquasher.json": 30 | return NormalTransformer.squashBakedQuads; 31 | case "mixins.modfixes_immersiveengineering.json": 32 | return NormalConfig.instance.fixBlockIEBaseArrayIndexOutOfBoundsException && Loader.isModLoaded("immersiveengineering"); 33 | case "mixins.modfixes_evilcraftcompat.json": 34 | return NormalConfig.instance.repairEvilCraftEIOCompat && Loader.isModLoaded("evilcraftcompat") && Loader.isModLoaded("enderio") && 35 | Loader.instance().getIndexedModList().get("enderio").getVersion().equals("5.3.70"); // Only apply on newer EIO versions where compat was broken 36 | case "mixins.modfixes_ebwizardry.json": 37 | return NormalConfig.instance.optimizeArcaneLockRendering && Loader.isModLoaded("ebwizardry"); 38 | case "mixins.modfixes_xu2.json": 39 | return (NormalConfig.instance.fixXU2CrafterCrash || NormalConfig.instance.disableXU2CrafterRendering) && Loader.isModLoaded("extrautils2"); 40 | case "mixins.searchtree_mod.json": 41 | return NormalConfig.instance.replaceSearchTreeWithJEISearching && Loader.isModLoaded("jei"); 42 | case "mixins.modfixes_astralsorcery.json": 43 | return NormalConfig.instance.optimizeAmuletRelatedFunctions && Loader.isModLoaded("astralsorcery"); 44 | case "mixins.capability_astralsorcery.json": 45 | return NormalConfig.instance.fixAmuletHolderCapability && Loader.isModLoaded("astralsorcery"); 46 | case "mixins.modfixes_b3m.json": 47 | return NormalConfig.instance.resourceLocationCanonicalization && Loader.isModLoaded("B3M"); // Stupid 48 | } 49 | return false; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/core/NormalMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.core; 2 | 3 | import org.objectweb.asm.tree.ClassNode; 4 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 5 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 6 | import mirror.normalasm.config.NormalConfig; 7 | import mirror.normalasm.core.classfactories.BakedQuadRedirectorFactory; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | public class NormalMixinPlugin implements IMixinConfigPlugin { 13 | 14 | static { 15 | if (NormalLoadingPlugin.isClient && NormalTransformer.squashBakedQuads) { 16 | BakedQuadRedirectorFactory.generateRedirectorClass(); 17 | } 18 | } 19 | 20 | @Override 21 | public void onLoad(String mixinPackage) { } 22 | 23 | @Override 24 | public String getRefMapperConfig() { 25 | return null; 26 | } 27 | 28 | @Override 29 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 30 | switch (mixinClassName) { 31 | case "mirror.normalasm.common.forgefixes.mixins.ChunkMixin": 32 | return NormalConfig.instance.fixTileEntityOnLoadCME; 33 | case "mirror.normalasm.common.forgefixes.mixins.EntityEntryMixin": 34 | return NormalConfig.instance.fasterEntitySpawnPreparation; 35 | case "mirror.normalasm.common.forgefixes.mixins.DimensionTypeMixin": 36 | return NormalConfig.instance.fixDimensionTypesInliningCrash; 37 | case "mirror.normalasm.client.screenshot.mixins.MinecraftMixin": 38 | return NormalConfig.instance.copyScreenshotToClipboard; 39 | case "mirror.normalasm.client.screenshot.mixins.ScreenShotHelperMixin": 40 | return NormalConfig.instance.releaseScreenshotCache; 41 | } 42 | return true; 43 | } 44 | 45 | @Override 46 | public void acceptTargets(Set myTargets, Set otherTargets) { } 47 | 48 | @Override 49 | public List getMixins() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } 55 | 56 | @Override 57 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/patches/RenderGlobalPatch.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.patches; 2 | 3 | import net.minecraft.client.renderer.chunk.RenderChunk; 4 | import net.minecraft.entity.Entity; 5 | import net.minecraft.util.ClassInheritanceMultiMap; 6 | import net.minecraft.util.math.AxisAlignedBB; 7 | import net.minecraft.world.chunk.Chunk; 8 | 9 | @SuppressWarnings("unused") 10 | public class RenderGlobalPatch { 11 | /** 12 | * Minecraft is transformed to call this method when it tries to do culling checks. Return a bounding box that 13 | * includes all entities, so culling works as it should. 14 | */ 15 | public static AxisAlignedBB getCorrectBoundingBox(RenderChunk renderChunk) { 16 | int subChunkYPos = renderChunk.getPosition().getY(); 17 | Chunk chunk = renderChunk.getWorld().getChunk(renderChunk.getPosition()); 18 | int subChunkList = subChunkYPos / 16; 19 | /* Make sure there is actually going to be an entity list, to be on the safe side */ 20 | if (subChunkList < 0 || subChunkList >= chunk.getEntityLists().length) { 21 | return renderChunk.boundingBox; 22 | } 23 | ClassInheritanceMultiMap entityMap = chunk.getEntityLists()[subChunkList]; 24 | if (!entityMap.isEmpty()) { 25 | /* Use local variables to avoid GC churn during rendering */ 26 | double minX = renderChunk.boundingBox.minX, minY = renderChunk.boundingBox.minY, minZ = renderChunk.boundingBox.minZ; 27 | double maxX = renderChunk.boundingBox.maxX, maxY = renderChunk.boundingBox.maxY, maxZ = renderChunk.boundingBox.maxZ; 28 | for (Entity entity : entityMap) { 29 | AxisAlignedBB entityBox = entity.getRenderBoundingBox(); 30 | minX = Math.min(minX, entityBox.minX - 0.5); 31 | minY = Math.min(minY, entityBox.minY - 0.5); 32 | minZ = Math.min(minZ, entityBox.minZ - 0.5); 33 | maxX = Math.max(maxX, entityBox.maxX + 0.5); 34 | maxY = Math.max(maxY, entityBox.maxY + 0.5); 35 | maxZ = Math.max(maxZ, entityBox.maxZ + 0.5); 36 | } 37 | return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); 38 | } 39 | return renderChunk.boundingBox; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/vanillafix/bugfixes/mixins/MixinBlockStateContainer.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.vanillafix.bugfixes.mixins; 2 | 3 | import net.minecraft.util.BitArray; 4 | import net.minecraft.world.chunk.BlockStateContainer; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Redirect; 8 | 9 | /** 10 | * Provided by Aaron from Sponge. All code on this page is used in rights 11 | * with the Sponge license and was taken from SpongeCommon 12 | */ 13 | @Mixin(BlockStateContainer.class) 14 | public class MixinBlockStateContainer { 15 | 16 | /** 17 | * Serializing a BlockStateContainer to a PacketBuffer is done in two parts: 18 | * calculating the size of the allocation needed in the PacketBuffer, and actually 19 | * writing it. 20 | * 21 | * When the BlockStateContainer is actually written to the PacketBuffer, 22 | * its 'storage.BitArray.getBackingLongArray' is written as a VarInt-length-prefixed 23 | * array. However, when calculating the size of the allocation needed, the size of 24 | * 'storage.size()' encoded as a VarInt is used, not the size of 'getBackingLongArray' 25 | * encoded as a VarInt. If the size of getBackingLongArray is ever large enough to require 26 | * an extra byte in its VarInt encoding, the allocated buffer will be too small, resuling in a crash. 27 | * 28 | * To fix this issue, we calculate the length of getBackingLongArray encoded as a VarInt, 29 | * when we're calculating the necessary allocation size. 30 | * @param bits 31 | * @return 32 | */ 33 | @Redirect(method = "getSerializedSize", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/BitArray;size()I")) 34 | private int onGetStorageSize$FixVanillaBug(BitArray bits) { 35 | return bits.getBackingLongArray().length; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/vanillafix/bugfixes/mixins/MixinEntity.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.vanillafix.bugfixes.mixins; 2 | 3 | import net.minecraft.block.state.IBlockState; 4 | import net.minecraft.entity.Entity; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.world.World; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | 13 | @Mixin(value = Entity.class, priority = 500) 14 | public abstract class MixinEntity { 15 | @Shadow public float fallDistance; 16 | @Shadow public World world; 17 | 18 | /** 19 | * @reason Fixes a vanilla bug where the entity's fall distance is not updated before invoking the 20 | * block's onFallenUpon when it falls on the ground, meaning that the last fall state update won't 21 | * be included in the fall distance. 22 | */ 23 | @Inject(method = "updateFallState", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;onFallenUpon(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;F)V")) 24 | private void beforeOnFallenUpon(double y, boolean onGroundIn, IBlockState state, BlockPos pos, CallbackInfo ci) { 25 | if (y < 0) fallDistance -= y; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/vanillafix/bugfixes/mixins/MixinEntityPlayerMP.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.vanillafix.bugfixes.mixins; 2 | 3 | import com.mojang.authlib.GameProfile; 4 | import net.minecraft.entity.player.EntityPlayer; 5 | import net.minecraft.entity.player.EntityPlayerMP; 6 | import net.minecraft.server.MinecraftServer; 7 | import net.minecraft.server.management.PlayerInteractionManager; 8 | import net.minecraft.util.DamageSource; 9 | import net.minecraft.world.World; 10 | import net.minecraft.world.WorldServer; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Shadow; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.Redirect; 16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 17 | 18 | @Mixin(EntityPlayerMP.class) 19 | public abstract class MixinEntityPlayerMP extends EntityPlayer { 20 | @Shadow public abstract void handleFalling(double y, boolean onGroundIn); 21 | 22 | public MixinEntityPlayerMP(World worldIn, GameProfile gameProfileIn) {super(worldIn, gameProfileIn);} 23 | 24 | /** 25 | * @reason Entities should not be invulnerable after dimension change, players could 26 | * intentionally abuse this. isInvulnerableDimensionChange is now only to prevent 27 | * teleporting the player again (in the other nether portal before the client had the 28 | * time to confirm the teleport). 29 | */ 30 | @Redirect(method = "isEntityInvulnerable", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/EntityPlayer;isEntityInvulnerable(Lnet/minecraft/util/DamageSource;)Z")) 31 | private boolean isEntityInvulnerable(EntityPlayer entityPlayer, DamageSource source) { 32 | return false; 33 | } 34 | 35 | /** 36 | * @reason This is incorrectly set to 1, but not noticable in vanilla since the move logic 37 | * trusts the client about its y position after a move due to a bug: (y > -0.5 || y 38 | * < 0.5) rather than &&. If this is fixed, a player standing in moving water at the 39 | * edge of a block is considered to have "moved wrongly" and teleported onto the block. 40 | *

41 | * Leaving this to 1 would also allow hacked clients to step up blocks without having 42 | * to jump (not increasing hunger). 43 | */ 44 | @Inject(method = "", at = @At("RETURN")) 45 | private void afterInit(MinecraftServer server, WorldServer worldIn, GameProfile profile, PlayerInteractionManager interactionManagerIn, CallbackInfo ci) { 46 | stepHeight = 0.7F; 47 | } 48 | 49 | // /** 50 | // * @reason Anti-cheat: Calculate fall damage even if not receiving move packets from the client. 51 | // * Otherwise, the client could disconnect without sending move packets to avoid fall damage. 52 | // * 53 | // * Also simplifies fall logic a lot. 54 | // */ 55 | // @Inject(method = "updateFallState", at = @At("HEAD")) 56 | // public void updateFallState(double y, boolean onGround, IBlockState state, BlockPos pos, CallbackInfo ci) { 57 | // handleFalling(y, this.onGround); 58 | // } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/vanillafix/bugfixes/mixins/MixinEntityTrackerEntry.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.vanillafix.bugfixes.mixins; 2 | 3 | import net.minecraft.entity.Entity; 4 | import net.minecraft.entity.EntityLiving; 5 | import net.minecraft.entity.EntityTrackerEntry; 6 | import net.minecraft.entity.player.EntityPlayerMP; 7 | import net.minecraft.network.play.server.SPacketEntityAttach; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | 15 | // TODO: include? 16 | @Mixin(EntityTrackerEntry.class) 17 | public class MixinEntityTrackerEntry { 18 | 19 | @Shadow @Final private Entity trackedEntity; 20 | 21 | @Inject(method = "updatePlayerEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;addTrackingPlayer(Lnet/minecraft/entity/player/EntityPlayerMP;)V")) 22 | public void sendAttachPacketIfNecessary(EntityPlayerMP playerMP, CallbackInfo ci) { 23 | if (trackedEntity instanceof EntityLiving) { 24 | playerMP.connection.sendPacket(new SPacketEntityAttach(trackedEntity, ((EntityLiving) trackedEntity).getLeashHolder())); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/mirror/normalasm/vanillafix/bugfixes/mixins/client/MixinIntegratedServer.java: -------------------------------------------------------------------------------- 1 | package mirror.normalasm.vanillafix.bugfixes.mixins.client; 2 | 3 | import net.minecraft.server.integrated.IntegratedServer; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.At; 6 | import org.spongepowered.asm.mixin.injection.Redirect; 7 | 8 | import java.util.concurrent.Future; 9 | 10 | // TODO: include? 11 | @Mixin(IntegratedServer.class) 12 | public abstract class MixinIntegratedServer { 13 | /** 14 | * @reason If the everyone leaves the integrated server, and a shutdown is then 15 | * initiated, there is a possibility that by the time initiateShutdown is called, 16 | * the server is still running but will shut down before running scheduled tasks. 17 | * Don't wait for the task to run, since that may never happen. 18 | */ 19 | @Redirect(method = "initiateShutdown", at = @At(value = "INVOKE", target = "Lcom/google/common/util/concurrent/Futures;getUnchecked(Ljava/util/concurrent/Future;)Ljava/lang/Object;", ordinal = 0)) 20 | private V getUnchecked(Future future) { 21 | return null; 22 | } 23 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/normalasm_at.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirrorcult/NormalASM/d3e8bddc7a81a662feb19acb7ebf8d008e237600/src/main/resources/META-INF/normalasm_at.cfg -------------------------------------------------------------------------------- /src/main/resources/assets/normalasm/lang/de_de.lang: -------------------------------------------------------------------------------- 1 | normalasm.gui.getLink=Link erhalten 2 | normalasm.gui.failed=[Fehlgeschlagen] 3 | normalasm.crashscreen.title=Minecraft ist abgestürzt! 4 | normalasm.crashscreen.summary=Minecraft ist ein Problem unterlaufen und ist abgestürzt. 5 | 6 | normalasm.crashscreen.paragraph1.line1=Folgende Modifikation(en) wurde(n) als mögliche Ursache identifiziert: 7 | 8 | normalasm.crashscreen.paragraph2.line1=Klicke auf einen beliebigen Mod in der Liste, um auf die Website zu gelangen. 9 | normalasm.crashscreen.paragraph2.line2=Ein Bericht wurde erstellt und kann hier gefunden werden (Klick): 10 | 11 | normalasm.crashscreen.reportSaveFailed=[FEHLER BEIM SPEICHERN, SIEHE LOG] 12 | 13 | normalasm.crashscreen.paragraph3.line1=Klicke auf die Schaltfläche "Link erhalten", um ihn im Browser zu 14 | normalasm.crashscreen.paragraph3.line2=öffnen. Du bist aufgefordert, diesen Bericht an den Modhersteller 15 | normalasm.crashscreen.paragraph3.line3=zu senden, um ihm zu helfen, das Problem zu beheben. Da NormalASM 16 | normalasm.crashscreen.paragraph3.line4=installiert ist, kannst du trotz des Absturzes weiterspielen. 17 | -------------------------------------------------------------------------------- /src/main/resources/assets/normalasm/lang/fr_fr.lang: -------------------------------------------------------------------------------- 1 | normalasm.gui.getLink=Obtenir un lien 2 | normalasm.gui.failed=[Échoué] 3 | normalasm.gui.keepPlaying=Continuer à jouer 4 | 5 | normalasm.crashscreen.title=Minecraft a crashé! 6 | normalasm.crashscreen.summary=Minecraft a rencontré un problème et a crashé. 7 | 8 | normalasm.crashscreen.paragraph1.line1=Ces mod(s) ont été identifiés comme des causes potentielles: 9 | 10 | normalasm.crashscreen.unknownCause=Cause inconnue 11 | normalasm.crashscreen.identificationErrored=[Problème dans l'identification, raportez à NormalASM] 12 | 13 | normalasm.crashscreen.paragraph2.line1=Cliquez n'importe quel mod dans la liste pour aller a leur page 14 | normalasm.crashscreen.paragraph2.line2=pour du support. Un raport a été génére et se trouve ici (cliquez): 15 | 16 | normalasm.crashscreen.reportSaveFailed=[Erreur durant la sauvegarde, voir le log] 17 | 18 | normalasm.crashscreen.paragraph3.line1=Cliquez le bouton « Obtenir un lien » pour l'ouvrir dans votre 19 | normalasm.crashscreen.paragraph3.line2=navigateur web. Vous êtez encouragé de l'envoyer à l'auteur du 20 | normalasm.crashscreen.paragraph3.line3=mod pour l'aider à résoudre le problême. Vu que NormalASM est 21 | normalasm.crashscreen.paragraph3.line4=installé, vous pouvez continuer a jouer malgré le crash. 22 | 23 | normalasm.warnscreen.title=Problème potentiel trouvé! 24 | normalasm.warnscreen.summary=Minecraft a rencontré un problème. 25 | 26 | normalasm.warnscreen.paragraph1.line1=Ceci n'a pas causé un crash, mais il y aura problement des 27 | normalasm.warnscreen.paragraph1.line2=conséquances comme la corruption du monde, ou des choses brisées. 28 | normalasm.warnscreen.paragraph1.line3=Ces mod(s) ont été identifiés comme des causes potentielles: 29 | 30 | normalasm.warnscreen.paragraph3.line1=Cliquez le bouton « Obtenir un lien » pour l'ouvrir dans votre 31 | normalasm.warnscreen.paragraph3.line2=navigateur web. Vous êtez encouragé de l'envoyer à l'auteur du 32 | normalasm.warnscreen.paragraph3.line3=mod pour l'aider à résoudre le problême. Vous pouvez continuer 33 | normalasm.warnscreen.paragraph3.line4=à jouer, mais sachez qu'il y aura surement d'autres problèmes. 34 | normalasm.warnscreen.paragraph3.line5=Ce message peut être désactivé dans la configuration du mod. 35 | -------------------------------------------------------------------------------- /src/main/resources/assets/normalasm/lang/ro_ro.lang: -------------------------------------------------------------------------------- 1 | normalasm.gui.getLink=Obțineți un link 2 | normalasm.gui.failed=[Eșuat] 3 | 4 | normalasm.crashscreen.title=Minecraft a crash! 5 | normalasm.crashscreen.summary=Minecraft întâmpinat o problemă și a crash 6 | 7 | normalasm.crashscreen.paragraph1.line1=Următoarele mod(uri) au fost identificate ca cauze posibile: 8 | 9 | normalasm.crashscreen.paragraph2.line1=Faceți click pe ori care mod din această lista pentru a merge 10 | normalasm.crashscreen.paragraph2.line2=pe site-ul lor pentru suport. Un raport poate fi găsit aici: 11 | 12 | normalasm.crashscreen.reportSaveFailed=[Eroare salvând raportul, vedeți log-ul] 13 | 14 | normalasm.crashscreen.paragraph3.line1=Faceți click pe butonul "Obțineți un link" pentru a-l deschide 15 | normalasm.crashscreen.paragraph3.line2=in browser. Sunteți encurajați să-l trimiteți la autorul modului 16 | normalasm.crashscreen.paragraph3.line3=pentru a-l ajuta să rezolve problema. Fiind că NormalASM e 17 | normalasm.crashscreen.paragraph3.line4=instalat, puteți continua de a juca în ciuda crash-ului. 18 | -------------------------------------------------------------------------------- /src/main/resources/assets/normalasm/lang/zh_cn.lang: -------------------------------------------------------------------------------- 1 | normalasm.gui.getLink=获取链接 2 | normalasm.gui.failed=[失败] 3 | normalasm.gui.keepPlaying=继续游戏 4 | normalasm.gui.restart=重启Minecraft 5 | 6 | normalasm.crashscreen.title=Minecraft崩溃啦! 7 | normalasm.crashscreen.summary=Minecraft遇到一个问题崩溃了。 8 | 9 | normalasm.crashscreen.paragraph1.line1=下列的mod被确定为崩溃的可能原因: 10 | 11 | normalasm.crashscreen.unknownCause=未知 12 | normalasm.crashscreen.identificationErrored=[鉴别错误,请报告给NormalASM] 13 | 14 | normalasm.crashscreen.paragraph2.line1=点击列表中的任意mod即可访问它们的网站获取技术支持。 15 | normalasm.crashscreen.paragraph2.line2=一份报告已经生成,你可以在这里找到(点击): 16 | 17 | normalasm.crashscreen.reportSaveFailed=[保存报告错误,请查看日志] 18 | 19 | normalasm.crashscreen.paragraph3.line1=点击"获取链接"按钮在你的浏览器中打开它。 20 | normalasm.crashscreen.paragraph3.line2=我们建议您将此报告发送给mod的作者以帮助它们修复问题。 21 | normalasm.crashscreen.paragraph3.line3=由于安装了NormalASM,尽管发生了崩溃但是你可以继续游戏。 22 | normalasm.crashscreen.paragraph3.line4= 23 | 24 | normalasm.initerrorscreen.title=Minecraft未能启动! 25 | normalasm.initerrorscreen.summary=启动过程中一个错误阻止了Minecraft的启动 26 | 27 | normalasm.initerrorscreen.paragraph3.line1=点击"获取链接"按钮在你的浏览器中打开它。 28 | normalasm.initerrorscreen.paragraph3.line2=我们建议您将此报告发送给mod的作者以帮助它们修复问题。 29 | normalasm.initerrorscreen.paragraph3.line3=不幸的是,在发生这个错误之后继续加载minecraft时不可能的。 30 | normalasm.initerrorscreen.paragraph3.line4= 31 | 32 | normalasm.warnscreen.title=发现潜在问题! 33 | normalasm.warnscreen.summary=Minecraft遇到了问题。 34 | 35 | normalasm.warnscreen.paragraph1.line1=This did not cause a crash, but there will likely still be 36 | normalasm.warnscreen.paragraph1.line2=consequences such as world corruption, or broken features. 37 | normalasm.warnscreen.paragraph1.line3=The following mod(s) have been identified as potential causes: 38 | 39 | normalasm.warnscreen.paragraph3.line1=点击"获取链接"按钮在你的浏览器中打开它。 40 | normalasm.warnscreen.paragraph3.line2=我们建议您将此报告发送给mod的作者以帮助它们修复问题。 41 | normalasm.warnscreen.paragraph3.line3=您可以继续游戏,但请注意,您稍后可能会遇到一些问题。 42 | normalasm.warnscreen.paragraph3.line4=可以在 Mods > NormalASM > Config > Crashes 中禁用此警告。 43 | normalasm.warnscreen.paragraph3.line5= 44 | 45 | normalasm.notification.title.unknown=发生未知问题! 46 | normalasm.notification.title.mod=%s 遇到问题! 47 | normalasm.notification.description=按Ctrl + I获取更多信息 48 | 49 | normalasm.fixes=启用/禁用 修复 50 | normalasm.fixes.tooltip=控制启用和禁用哪些修复。 51 | normalasm.crashes=崩溃选项 52 | normalasm.crashes.tooltip=关于如何处理崩溃的选项 53 | normalasm.crashes.problemAction.log=日志 54 | normalasm.crashes.problemAction.notification=通知 55 | normalasm.crashes.problemAction.warningScreen=警告屏幕 56 | normalasm.crashes.problemAction.crash=崩溃 57 | normalasm.crashes.scheduledTaskproblemAction=计划任务例外操作 58 | normalasm.crashes.scheduledTaskproblemAction.tooltip=计划任务引发异常时应该发生什么 59 | normalasm.crashes.errorNotificationDuration=错误通知持续时间 60 | normalasm.crashes.errorNotificationDuration.tooltip=以毫秒为单位显示错误通知的时间 61 | normalasm.crashes.replaceErrorNotifications=替换错误通知 62 | normalasm.crashes.replaceErrorNotifications.tooltip=当连续出现多个错误时,请替换通知而不是顺序出现更多通知 63 | normalasm.crashes.hasteURL=Haste URL 64 | normalasm.crashes.hasteURL.tooltip=The URL to the root of the haste instance to upload crash reports to, without a trailing slash. 65 | 66 | 67 | normalasm.debug.switch_profiler.help=F3 + S = Cycle client <-> integrated server profiler 68 | normalasm.debug.switch_profiler.server=使用服务器分析器 69 | normalasm.debug.switch_profiler.client=使用客户端分析器 70 | -------------------------------------------------------------------------------- /src/main/resources/assets/normalasm/normalasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirrorcult/NormalASM/d3e8bddc7a81a662feb19acb7ebf8d008e237600/src/main/resources/assets/normalasm/normalasm.png -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "normalasm", 4 | "name": "NormalASM", 5 | "description": "NormalASM has bytecode manipulated your game.", 6 | "version": "${version}", 7 | "mcversion": "${mcversion}", 8 | "url": "https://github.com/mirrorcult/NormalASM", 9 | "updateUrl": "", 10 | "authorList": ["Rongmario"], 11 | "logoFile": "assets/normalasm/normalasm.png", 12 | "screenshots": [], 13 | "dependencies": [] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /src/main/resources/mixins.bakedquadsquasher.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.models.bakedquad.mixins", 3 | "plugin": "mirror.normalasm.core.NormalMixinPlugin", 4 | "refmap": "mixins.normalasm.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.8", 7 | "compatibilityLevel": "JAVA_8", 8 | "client": [ 9 | "HaxMixin", 10 | "NewBakedQuadCallsRedirector" 11 | ] 12 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.bucket.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.models.bucket.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "ModelDynBucketMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.capability.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.capability.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "ItemStackMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.capability_astralsorcery.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.capability.astralsorcery.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "AmuletHolderCapabilityProviderAccessor", 9 | "EnchantmentUpgradeHelperMixin" 10 | ] 11 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.crashes.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.crashes.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "CrashReportCategory_EntryInvoker", 9 | "CrashReportCategoryMixin", 10 | "CrashReportMixin", 11 | "EntityMixin", 12 | "TileEntityMixin", 13 | "UtilMixin" 14 | ], 15 | "client": [ 16 | "BufferBuilderMixin", 17 | "IntegratedServerMixin", 18 | "MinecraftMixin", 19 | "TileEntityRenderDispatcherMixin" 20 | ] 21 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.datastructures_modelmanager.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.models.datastructures.modelmanager.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "ModelManagerMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.devenv.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.devenv.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "FMLModContainerMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.efficienthashing.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.efficienthashing.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "BlockPosMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.fix_mc129057.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.mcfixes.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "mc129057.InventoryPlayerMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.fix_mc129556.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.mcfixes.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "mc129556.MinecraftMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.fix_mc_skindownloading.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.mcfixes.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "skindownloading.ThreadDownloadImageDataMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.forgefixes.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.forgefixes.mixins", 3 | "plugin": "mirror.normalasm.core.NormalMixinPlugin", 4 | "refmap": "mixins.normalasm.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.8", 7 | "compatibilityLevel": "JAVA_8", 8 | "mixins": [ 9 | "ChunkMixin", 10 | "DimensionTypeMixin", 11 | "EntityEntryMixin", 12 | "ForgeEventFactoryMixin" 13 | ] 14 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.internal.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.internal.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "CapabilityDispatcherMixin", 9 | "ItemStackMixin", 10 | "LoadControllerMixin" 11 | ], 12 | "client": [ 13 | "TextureManagerAccessor", 14 | "TileEntityMixin" 15 | ] 16 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.lockcode.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.lockcode.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "LockCodeMixin" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.misc_fluidregistry.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.misc_fluidregistry.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "FluidRegistryMixin" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.modfixes_astralsorcery.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.modfixes.astralsorcery.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "EnchantmentUpgradeHelperInvoker", 9 | "ItemEnchantmentAmuletMixin", 10 | "PlayerAmuletHandlerMixin" 11 | ], 12 | "injectors": { 13 | "defaultRequire": 1 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.modfixes_b3m.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.modfixes.b3m.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "injectors": { 8 | "defaultRequire": 1 9 | }, 10 | "mixins": [ 11 | "B3M_CoreMixin" 12 | ] 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.modfixes_ebwizardry.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.modfixes.ebwizardry.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "injectors": { 8 | "defaultRequire": 1 9 | }, 10 | "client": [ 11 | "RenderArcaneLockMixin" 12 | ] 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.modfixes_evilcraftcompat.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.modfixes.evilcraftcompat.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "injectors": { 8 | "defaultRequire": 1 9 | }, 10 | "mixins": [ 11 | "EnderIORecipeManagerMixin" 12 | ] 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.modfixes_immersiveengineering.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.modfixes.immersiveengineering.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "BlockIEBaseMixin" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.modfixes_xu2.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.modfixes.xu2.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "injectors": { 8 | "defaultRequire": 1 9 | }, 10 | "client": [ 11 | "XUTESRBaseMixin", 12 | "TileCrafterMixin" 13 | ] 14 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.ondemand_sprites.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.sprite.ondemand.mixins", 3 | "plugin": "mirror.normalasm.core.NormalMixinPlugin", 4 | "refmap": "mixins.normalasm.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.8", 7 | "compatibilityLevel": "JAVA_8", 8 | "client": [ 9 | "BlockFluidRendererMixin", 10 | "BlockModelRendererMixin", 11 | "BufferBuilderMixin", 12 | "ChunkCompileTaskGeneratorMixin", 13 | "CompiledChunkMixin", 14 | "ContainerLocalRenderInformationAccessor", 15 | "ForgeBlockModelRendererMixin", 16 | "ItemRendererMixin", 17 | "RenderGlobalAccessor", 18 | "RenderItemMixin", 19 | "TextureAtlasSpriteMixin", 20 | "TextureManagerMixin", 21 | "TextureMapMixin", 22 | "VertexLighterFlatMixin" 23 | ] 24 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.recipes.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.recipes.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "FurnaceRecipesMixin" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.registries.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.registries.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "RegistrySimpleMixin" 9 | ], 10 | "client": [ 11 | "SoundRegistryMixin" 12 | ], 13 | "injectors": { 14 | "defaultRequire": 1 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.rendering.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.rendering.mixins", 3 | "plugin": "mirror.normalasm.core.NormalMixinPlugin", 4 | "refmap": "mixins.normalasm.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.8", 7 | "compatibilityLevel": "JAVA_8", 8 | "client": [ 9 | "VisGraphMixin" 10 | ], 11 | "injectors": { 12 | "defaultRequire": 1 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.resolve_mc2071.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.mcfixes.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "mc2071.EntityPlayerSPMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.screenshot.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.screenshot.mixins", 3 | "plugin": "mirror.normalasm.core.NormalMixinPlugin", 4 | "refmap": "mixins.normalasm.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.8", 7 | "compatibilityLevel": "JAVA_8", 8 | "client": [ 9 | "MinecraftMixin", 10 | "ScreenShotHelperInvoker", 11 | "ScreenShotHelperMixin" 12 | ] 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.searchtree_mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.searchtree.mixins.mod", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "IngredientFilterInvoker" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.searchtree_vanilla.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.client.searchtree.mixins.vanilla", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "MinecraftMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.singletonevents.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.singletonevents.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "FMLCommonHandlerMixin", 9 | "ForgeEventFactoryMixin", 10 | "blocks.BlockEventMixin", 11 | "blocks.NeighborNotifyEventMixin", 12 | "capabilities.AttachCapabilitiesEventMixin", 13 | "gameevent.PlayerTickEventMixin", 14 | "gameevent.RenderTickEventMixin", 15 | "gameevent.TickEventMixin", 16 | "gameevent.WorldTickEventMixin" 17 | ] 18 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.stripitemstack.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.stripitemstack.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "ItemStackMixin" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.vanities.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.common.vanities.mixins", 3 | "refmap": "mixins.normalasm.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "FMLCommonHandlerMixin" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixins.vfix_bugfixes.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "mirror.normalasm.vanillafix.bugfixes.mixins", 3 | "required": true, 4 | "refmap": "mixins.normalasm.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.7", 7 | "compatibilityLevel": "JAVA_8", 8 | "mixins": [ 9 | "MixinEntityPlayerMP", 10 | "MixinEntity", 11 | "MixinBlockStateContainer", 12 | "MixinEntityTrackerEntry" 13 | ], 14 | "client": [ 15 | "client.MixinIntegratedServer" 16 | ], 17 | "injectors": { 18 | "maxShiftBy": 10 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 3, 4 | "description": "NormalASM" 5 | } 6 | } 7 | --------------------------------------------------------------------------------