├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── java └── git │ └── jbredwards │ └── fluidlogged_api │ ├── api │ ├── asm │ │ ├── AbstractClassTransformer.java │ │ ├── BasicLoadingPlugin.java │ │ └── IASMPlugin.java │ ├── block │ │ ├── BlockWaterloggedPlant.java │ │ └── IFluidloggable.java │ ├── capability │ │ ├── CapabilityProvider.java │ │ ├── IFluidStateCapability.java │ │ ├── IFluidStateContainer.java │ │ └── IPosSerializer.java │ ├── datafix │ │ ├── FluidMappingData.java │ │ └── IFluidloggedDataMapper.java │ ├── event │ │ ├── FluidloggableEvent.java │ │ ├── FluidloggedAPIConfigsEvent.java │ │ └── FluidloggedEvent.java │ ├── fluid │ │ ├── ICompatibleFluid.java │ │ ├── IFlowCostFluid.java │ │ └── IFluidloggableFluid.java │ ├── network │ │ ├── IClientMessageHandler.java │ │ ├── MessageUtils.java │ │ └── message │ │ │ └── AbstractMessage.java │ ├── util │ │ ├── FluidState.java │ │ └── FluidloggedUtils.java │ └── world │ │ ├── IBlockAccessWrapper.java │ │ ├── IChunkProvider.java │ │ ├── IFluidStatePrimer.java │ │ ├── IFluidStateProvider.java │ │ ├── IWorldChunkProvider.java │ │ └── IWorldProvider.java │ └── mod │ ├── FluidloggedAPI.java │ ├── asm │ ├── ASMHandler.java │ ├── iface │ │ ├── ICanFluidFlowHandler.java │ │ ├── IConditionalFluid.java │ │ ├── IConfigAccessor.java │ │ ├── IConfigFluidBox.java │ │ ├── IDefaultFluidState.java │ │ ├── IHardcodedCapability.java │ │ ├── ILevelFluidStateLookup.java │ │ ├── IModdedWall.java │ │ └── IWaterHeight.java │ ├── plugins │ │ ├── forge │ │ │ ├── PluginBlockFluidBase.java │ │ │ ├── PluginBlockFluidClassic.java │ │ │ ├── PluginBlockFluidFinite.java │ │ │ ├── PluginBlockSnapshot.java │ │ │ ├── PluginFluidBucketWrapper.java │ │ │ ├── PluginFluidUtil.java │ │ │ ├── PluginFluidWater.java │ │ │ ├── PluginForgeHooks.java │ │ │ ├── PluginModelFluid.java │ │ │ └── PluginUniversalBucket.java │ │ ├── modded │ │ │ ├── actually_additions │ │ │ │ └── PluginActuallyAdditions.java │ │ │ ├── appliedenergistics2 │ │ │ │ └── PluginAE2.java │ │ │ ├── astral_sorcery │ │ │ │ ├── PluginAstralSorcery.java │ │ │ │ ├── PluginAstralSorceryAccess.java │ │ │ │ └── PluginEntityCrystal.java │ │ │ ├── betweenlands │ │ │ │ ├── PluginBetweenlands.java │ │ │ │ ├── PluginBetweenlandsRubber.java │ │ │ │ ├── PluginBetweenlandsStates.java │ │ │ │ └── PluginBetweenlandsTarBeast.java │ │ │ ├── biomesoplenty │ │ │ │ ├── PluginBiomesOPlenty.java │ │ │ │ └── PluginBucketEventHandler.java │ │ │ ├── blue_skies │ │ │ │ └── PluginBlueSkies.java │ │ │ ├── botania │ │ │ │ ├── PluginBotania.java │ │ │ │ └── PluginGardenOfGlass.java │ │ │ ├── buildcraft │ │ │ │ ├── PluginBlockUtil.java │ │ │ │ ├── PluginTileFloodGate.java │ │ │ │ └── PluginTilePump.java │ │ │ ├── builders_wands │ │ │ │ └── PluginBuildersWands.java │ │ │ ├── cb_multipart │ │ │ │ └── PluginCBMultipart.java │ │ │ ├── ceramics │ │ │ │ └── PluginItemClayBucket.java │ │ │ ├── chiseled_me │ │ │ │ └── PluginChiseledMe.java │ │ │ ├── cofhcore │ │ │ │ └── PluginCoFHCore.java │ │ │ ├── crafttweaker │ │ │ │ └── PluginCraftTweaker.java │ │ │ ├── cubic_chunks │ │ │ │ └── PluginCubicChunks.java │ │ │ ├── dynamictrees │ │ │ │ ├── PluginBlockRootyWater.java │ │ │ │ └── PluginModelRootyWater.java │ │ │ ├── endercore │ │ │ │ └── PluginEnderCore.java │ │ │ ├── enderio │ │ │ │ ├── PluginEnderIO.java │ │ │ │ └── PluginEnderIOSponge.java │ │ │ ├── exnihilo │ │ │ │ └── PluginExNihiloCreatio.java │ │ │ ├── extrautils │ │ │ │ ├── PluginExtraUtilsAccessDelegate.java │ │ │ │ └── PluginExtraUtilsAccessServer.java │ │ │ ├── flopper │ │ │ │ └── PluginFlopper.java │ │ │ ├── galacticraft │ │ │ │ ├── PluginBlockGrating.java │ │ │ │ ├── PluginGCBlocks.java │ │ │ │ └── PluginGalacticraft.java │ │ │ ├── hesperus │ │ │ │ └── PluginHesperus.java │ │ │ ├── industrial_foregoing │ │ │ │ └── PluginIndustrialForegoing.java │ │ │ ├── industrial_renewal │ │ │ │ └── PluginIndustrialRenewal.java │ │ │ ├── lycanitesmobs │ │ │ │ ├── PluginLycanitesFluidBase.java │ │ │ │ ├── PluginLycanitesFluidMixing.java │ │ │ │ └── PluginLycanitesFluidSources.java │ │ │ ├── mekanism │ │ │ │ ├── PluginMekanismPump.java │ │ │ │ ├── PluginMekanismTank.java │ │ │ │ └── PluginMekanismUtils.java │ │ │ ├── nethercraft │ │ │ │ └── PluginNethercraftClassic.java │ │ │ ├── nothirium │ │ │ │ └── PluginNothirium.java │ │ │ ├── openblocks │ │ │ │ └── PluginOpenBlocks.java │ │ │ ├── optifine │ │ │ │ ├── PluginIResolvable.java │ │ │ │ ├── PluginOptifine.java │ │ │ │ └── PluginSVertexBuilder.java │ │ │ ├── plus_tweaks │ │ │ │ └── PluginPlusTweaks.java │ │ │ ├── projecte │ │ │ │ ├── PluginProjectEAmulet.java │ │ │ │ └── PluginProjectEProjectile.java │ │ │ ├── projectred │ │ │ │ └── PluginProjectRed.java │ │ │ ├── quantumflux │ │ │ │ └── PluginQuantumFlux.java │ │ │ ├── railcraft │ │ │ │ └── PluginRailcraft.java │ │ │ ├── random_things │ │ │ │ └── PluginRandomThings.java │ │ │ ├── reliquary │ │ │ │ └── PluginReliquary.java │ │ │ ├── sledgehammer │ │ │ │ └── PluginSledgehammer.java │ │ │ ├── spongeforge │ │ │ │ └── PluginSpongeForge.java │ │ │ ├── tfc │ │ │ │ ├── PluginTFCBlockFluid.java │ │ │ │ └── PluginTFCFluids.java │ │ │ ├── thermal_dynamics │ │ │ │ └── PluginThermalDynamics.java │ │ │ ├── thermal_foundation │ │ │ │ ├── PluginThermalAerotheum.java │ │ │ │ ├── PluginThermalFoundation.java │ │ │ │ └── PluginThermalGlowstone.java │ │ │ ├── tiny_progressions │ │ │ │ └── PluginTinyProgressions.java │ │ │ ├── tropicraft │ │ │ │ ├── PluginTropicraftBucket.java │ │ │ │ ├── PluginTropicraftFence.java │ │ │ │ ├── PluginTropicraftFluid.java │ │ │ │ ├── PluginTropicraftOverlays.java │ │ │ │ └── PluginTropicraftSand.java │ │ │ ├── twilight_forest │ │ │ │ └── PluginTwilightForest.java │ │ │ └── waila │ │ │ │ └── PluginWaila.java │ │ └── vanilla │ │ │ ├── block │ │ │ ├── PluginBlock.java │ │ │ ├── PluginBlockBarrier.java │ │ │ ├── PluginBlockBush.java │ │ │ ├── PluginBlockCocoa.java │ │ │ ├── PluginBlockConcretePowder.java │ │ │ ├── PluginBlockDoor.java │ │ │ ├── PluginBlockDynamicLiquid.java │ │ │ ├── PluginBlockFarmland.java │ │ │ ├── PluginBlockFire.java │ │ │ ├── PluginBlockFlowerPot.java │ │ │ ├── PluginBlockGrass.java │ │ │ ├── PluginBlockLilyPad.java │ │ │ ├── PluginBlockLiquid.java │ │ │ ├── PluginBlockReed.java │ │ │ ├── PluginBlockSkull.java │ │ │ ├── PluginBlockSponge.java │ │ │ ├── PluginBlockStairs.java │ │ │ ├── PluginBlockStateBase.java │ │ │ ├── PluginBlockStateContainer.java │ │ │ ├── PluginBlockStaticLiquid.java │ │ │ ├── PluginBlockTrapDoor.java │ │ │ └── PluginBlockWall.java │ │ │ ├── client │ │ │ ├── PluginActiveRenderInfo.java │ │ │ ├── PluginBlockFluidRenderer.java │ │ │ ├── PluginEntityPlayerSP.java │ │ │ ├── PluginEntityRenderer.java │ │ │ ├── PluginParticleRain.java │ │ │ ├── PluginRenderChunk.java │ │ │ ├── PluginWaterParticles.java │ │ │ └── PluginWorldClient.java │ │ │ ├── entity │ │ │ ├── PluginEntity.java │ │ │ ├── PluginEntityAIPanic.java │ │ │ ├── PluginEntityBoat.java │ │ │ ├── PluginEntityFishHook.java │ │ │ ├── PluginEntityItem.java │ │ │ ├── PluginEntityLivingBase.java │ │ │ ├── PluginEntityMinecart.java │ │ │ └── PluginRandomPositionGenerator.java │ │ │ ├── item │ │ │ ├── PluginItemArmorStand.java │ │ │ ├── PluginItemBucket.java │ │ │ ├── PluginItemGlassBottle.java │ │ │ └── PluginItemLilyPad.java │ │ │ └── world │ │ │ ├── PluginChunk.java │ │ │ ├── PluginChunkCache.java │ │ │ ├── PluginChunkPrimer.java │ │ │ ├── PluginDragonSpawnManager.java │ │ │ ├── PluginTemplate.java │ │ │ ├── PluginWorld.java │ │ │ ├── PluginWorldGenDungeons.java │ │ │ └── PluginWorldServer.java │ └── transformers │ │ ├── TransformerLevelProperty.java │ │ ├── TransformerMethodRedirects.java │ │ ├── TransformerModdedBoats.java │ │ ├── TransformerModdedWalls.java │ │ └── TransformerSmoothWater.java │ ├── client │ ├── ClientEventHandler.java │ ├── gui │ │ ├── ComponentConfigEntry.java │ │ ├── FluidloggedAPIGuiFactory.java │ │ └── GuiComponentConfig.java │ ├── model │ │ └── BakedModelFluid.java │ └── optifine │ │ └── OptifineHelper.java │ └── common │ ├── EventHandler.java │ ├── capability │ ├── FluidStateCapabilityVanilla.java │ ├── FluidStateCapabilityWrapped.java │ ├── cubicchunks │ │ ├── FluidStateCapabilityIColumn.java │ │ └── FluidStateCapabilityICube.java │ └── util │ │ ├── FluidStateLayer.java │ │ └── FluidStateStorage.java │ ├── command │ ├── CommandChildBase.java │ ├── CommandFluidloggedAPI.java │ ├── CommandPrint.java │ ├── CommandReloadConfig.java │ ├── CommandSetFluidState.java │ └── CommandTest.java │ ├── config │ ├── FluidloggedAPIConfig.java │ ├── FluidloggedAPIConfigs.java │ ├── handler │ │ ├── BlacklistConfigHandler.java │ │ ├── FluidTagsConfigHandler.java │ │ ├── LegacyConfigHandler.java │ │ ├── OnlineConfigHandler.java │ │ └── WhitelistConfigHandler.java │ └── util │ │ ├── ConfigPredicate.java │ │ ├── ConfigPredicateHelper.java │ │ └── ConfigPredicateOperation.java │ ├── datafix │ ├── FluidloggedAPIFixableData.java │ ├── LegacyDataFixer.java │ ├── ToFluidloggedDataFixer.java │ └── modded │ │ ├── DynamicTreesDataFixer.java │ │ ├── GalacticraftDataFixer.java │ │ └── TropicraftDataFixer.java │ ├── fluid │ ├── handler │ │ ├── FluidCollisionHandler.java │ │ ├── FluidExtendedStateHandler.java │ │ ├── FluidFlowHandler.java │ │ └── FluidMixHandler.java │ └── util │ │ ├── FluidCache.java │ │ ├── IFluidNeighborInfo.java │ │ ├── IFluidUpdateHelper.java │ │ ├── ISpecializedFluidNeighborInfo.java │ │ └── impl │ │ ├── FluidNeighborInfo.java │ │ └── SpecializedFluidNeighborInfo.java │ └── message │ ├── CMessageSyncGameRule.java │ ├── SMessageCommandPrint.java │ ├── SMessageSyncFluidState.java │ ├── SMessageSyncFluidStates.java │ ├── SMessageSyncGameRule.java │ ├── SMessageSyncRuntimeConfigs.java │ └── SMessageVaporizeEffects.java └── resources ├── META-INF └── fluidlogged_api_at.cfg ├── assets └── fluidlogged_api │ ├── fluidlogged_api │ ├── fluidTags.jsonc │ └── whitelist.jsonc │ └── lang │ └── en_us.lang ├── logo.png ├── mcmod.info └── pack.mcmeta /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help improve this mod 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Logs** 27 | If you have access to any logs, please link them [here](https://gist.github.com/). 28 | 29 | **Additional context** 30 | Add any other context about the problem here, this may include mods, plugins, etc. 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this mod 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.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 | *.txt 24 | -------------------------------------------------------------------------------- /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 | mod_version=3.0.6 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbredwards/Fluidlogged-API/42129e74dd3d8e3797cf5d907ecfb68fa35daf20/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip 6 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/asm/AbstractClassTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.asm; 7 | 8 | import net.minecraft.launchwrapper.IClassTransformer; 9 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 10 | 11 | import javax.annotation.Nonnull; 12 | import javax.annotation.Nullable; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | /** 17 | * An easy way of implementing {@link IASMPlugin IASMPlugin-based} transformers at runtime. 18 | * 19 | * @since 1.9.0 20 | * @author jbred 21 | * 22 | */ 23 | public abstract class AbstractClassTransformer implements IClassTransformer 24 | { 25 | /** 26 | * Used by {@link AbstractClassTransformer#transform} to find which {@link IASMPlugin} to apply. 27 | * This map should be filled in your transformer's constructor. 28 | * 29 | * @since 1.9.0 30 | */ 31 | @Nonnull 32 | protected final Map plugins = new HashMap<>(); 33 | 34 | /** 35 | * Inherited from {@link IClassTransformer}. This implementation applies transformations based on which 36 | * of your {@link AbstractClassTransformer#plugins} maps to the provided transformedName. 37 | * 38 | * @param name Name of the class to be transformed. This may be obfuscated. 39 | * @param transformedName Deobfuscated name of the class to be transformed. 40 | * @param basicClass Bytecode of the class to be transformed. 41 | * @return The bytecode to be used during runtime. 42 | * 43 | * @since 1.9.0 44 | * @author jbred 45 | */ 46 | @Nullable 47 | @Override 48 | public byte[] transform(@Nullable final String name, @Nullable final String transformedName, @Nullable final byte[] basicClass) { 49 | if(basicClass == null || transformedName == null) return basicClass; 50 | @Nullable final IASMPlugin plugin = plugins.get(transformedName); 51 | if(plugin == null) return basicClass; 52 | 53 | IASMPlugin.setActivePlugin(getPluginName()); 54 | @Nonnull final byte[] newClass = plugin.transform(basicClass, !FMLLaunchHandler.isDeobfuscatedEnvironment()); 55 | IASMPlugin.resetActivePlugin(); 56 | 57 | return newClass; 58 | } 59 | 60 | /** 61 | * @return The {@link net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name name} of the 62 | * {@link net.minecraftforge.fml.relauncher.IFMLLoadingPlugin IFMLLoadingPlugin} that owns 63 | * this transformer. This method is used to help print debug info to the console as your transformer's 64 | * {@link AbstractClassTransformer#plugins} are applied. 65 | * 66 | * @since 1.9.0 67 | * @author jbred 68 | */ 69 | @Nonnull 70 | public abstract String getPluginName(); 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/capability/CapabilityProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.capability; 7 | 8 | import com.google.common.base.Preconditions; 9 | import net.minecraft.nbt.NBTBase; 10 | import net.minecraft.util.EnumFacing; 11 | import net.minecraftforge.common.capabilities.Capability; 12 | import net.minecraftforge.common.capabilities.ICapabilitySerializable; 13 | 14 | import javax.annotation.Nonnull; 15 | import javax.annotation.Nullable; 16 | 17 | /** 18 | * A general-purpose capability provider class. 19 | * 20 | * @since 1.9.0 21 | * @author jbred 22 | * 23 | */ 24 | public class CapabilityProvider implements ICapabilitySerializable 25 | { 26 | @Nonnull public final Capability capability; 27 | @Nonnull public final T instance; 28 | @Nullable public final EnumFacing face; 29 | 30 | public CapabilityProvider(@Nullable Capability capabilityIn) { 31 | this(capabilityIn, null); 32 | } 33 | 34 | public CapabilityProvider(@Nullable Capability capabilityIn, @Nullable T instanceIn) { 35 | this(capabilityIn, instanceIn, null); 36 | } 37 | 38 | public CapabilityProvider(@Nullable Capability capabilityIn, @Nullable T instanceIn, @Nullable EnumFacing faceIn) { 39 | capability = Preconditions.checkNotNull(capabilityIn, "Capability is null, this should never happen!"); 40 | instance = instanceIn != null ? instanceIn : Preconditions.checkNotNull(capability.getDefaultInstance(), 41 | "Default instance of capability \"%s\" returned null: ", capability.getName()); 42 | 43 | face = faceIn; 44 | } 45 | 46 | @Override 47 | public boolean hasCapability(@Nullable Capability capabilityIn, @Nullable EnumFacing faceIn) { 48 | return capabilityIn == capability && face == faceIn; 49 | } 50 | 51 | @Nullable 52 | @Override 53 | public t getCapability(@Nullable Capability capabilityIn, @Nullable EnumFacing faceIn) { 54 | if(!hasCapability(capabilityIn, faceIn)) return null; 55 | else return capability.cast(instance); 56 | } 57 | 58 | @Nonnull 59 | @Override 60 | public NBTBase serializeNBT() { 61 | return Preconditions.checkNotNull(capability.writeNBT(instance, face), 62 | "NBT for capability \"%s\" returned null, please fix it: ", capability.getName()); 63 | } 64 | 65 | @Override 66 | public void deserializeNBT(@Nullable NBTBase nbt) { capability.readNBT(instance, face, nbt); } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/capability/IFluidStateCapability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.capability; 7 | 8 | import git.jbredwards.fluidlogged_api.mod.FluidloggedAPI; 9 | import git.jbredwards.fluidlogged_api.mod.asm.iface.IHardcodedCapability; 10 | import net.minecraft.nbt.NBTBase; 11 | import net.minecraft.util.ResourceLocation; 12 | import net.minecraftforge.common.capabilities.Capability; 13 | import net.minecraftforge.common.capabilities.CapabilityInject; 14 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 15 | import net.minecraftforge.common.util.INBTSerializable; 16 | 17 | import javax.annotation.Nonnull; 18 | import javax.annotation.Nullable; 19 | 20 | /** 21 | * Holds {@link IFluidStateContainer IFluidStateContainers}. All methods in this interface should only be used internally! If you're a modder, 22 | * see {@link git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils FluidloggedUtils}. 23 | * 24 | * @since 1.9.0 25 | * @author jbred 26 | * 27 | */ 28 | @SuppressWarnings("ConstantConditions") 29 | public interface IFluidStateCapability extends INBTSerializable 30 | { 31 | @CapabilityInject(IFluidStateCapability.class) 32 | @Nonnull Capability CAPABILITY = null; 33 | @Nonnull ResourceLocation CAPABILITY_ID = new ResourceLocation(FluidloggedAPI.MODID, "fluid_states"); 34 | 35 | /** 36 | * @param provider ICapabilityProvider. 37 | * @return This from a capability provider. 38 | * 39 | * @since 1.9.0 40 | * @author jbred 41 | */ 42 | @Nullable 43 | static IFluidStateCapability get(@Nullable final ICapabilityProvider provider) { 44 | if(provider instanceof IHardcodedCapability) return ((IHardcodedCapability)provider).getFluidStateCapability(); 45 | return provider != null && provider.hasCapability(CAPABILITY, null) ? provider.getCapability(CAPABILITY, null) : null; 46 | } 47 | 48 | /** 49 | * Having at minimum ONE container per 16x16x16 area of the world is expected. 50 | * @param y Y position (block position format, not chunk position format). 51 | * @return The container stored at the y position. 52 | * 53 | * @since 3.0.0 54 | * @author jbred 55 | */ 56 | @Nonnull 57 | IFluidStateContainer getContainer(final int y); 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/datafix/FluidMappingData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.datafix; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import net.minecraft.block.Block; 10 | 11 | import javax.annotation.Nonnull; 12 | import javax.annotation.Nullable; 13 | import java.util.Objects; 14 | 15 | /** 16 | * Used alongside {@link IFluidloggedDataMapper} to split data for "pseudo-fluidlogged" blocks into 17 | * real {@link FluidState FluidState data}. This class holds the new data to be set in the chunk, and 18 | * also allows the block itself to be changed (if desired). 19 | * 20 | * @since 3.0.0 21 | * @author jbred 22 | * 23 | */ 24 | public class FluidMappingData 25 | { 26 | @Nullable 27 | public Block block; 28 | public int meta = -1; 29 | 30 | @Nonnull 31 | public FluidState fluidState; 32 | public FluidMappingData(@Nonnull final FluidState fluidStateIn) { 33 | fluidState = Objects.requireNonNull(fluidStateIn); 34 | } 35 | 36 | /** 37 | * If this is not set, the existing block will be used. 38 | * @param blockIn The block to use (not the FluidState). 39 | * @return This FluidMappingData, for ease of use. 40 | * 41 | * @since 3.0.0 42 | * @author jbred 43 | */ 44 | @Nonnull 45 | public FluidMappingData withBlock(@Nonnull final Block blockIn) { 46 | block = Objects.requireNonNull(blockIn); 47 | return this; 48 | } 49 | 50 | /** 51 | * If this is not set, the existing block metadata will be used. 52 | * @param metaIn The block metadata to use (not the FluidState). 53 | * @return This FluidMappingData, for ease of use. 54 | * 55 | * @since 3.0.0 56 | * @author jbred 57 | */ 58 | @Nonnull 59 | public FluidMappingData withMetadata(final int metaIn) { 60 | meta = metaIn; 61 | return this; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/datafix/IFluidloggedDataMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.datafix; 7 | 8 | import com.google.common.collect.HashMultimap; 9 | import com.google.common.collect.Multimap; 10 | import net.minecraft.block.Block; 11 | 12 | import javax.annotation.Nonnull; 13 | import javax.annotation.Nullable; 14 | 15 | /** 16 | * Converts data for "pseudo-fluidlogged" blocks into real FluidState data, with the option of changing the block metadata. 17 | * Useful for mods that want to migrate to a Fluidlogged API dependency. 18 | * 19 | * @since 3.0.0 20 | * @author jbred 21 | * 22 | */ 23 | @FunctionalInterface 24 | public interface IFluidloggedDataMapper 25 | { 26 | /** 27 | * Holds all active {@link IFluidloggedDataMapper IFluidloggedDataMappers}, used by 28 | * {@link git.jbredwards.fluidlogged_api.mod.common.datafix.ToFluidloggedDataFixer ToFluidloggedDataFixer}. 29 | * 30 | * @since 3.0.0 31 | */ 32 | @Nonnull 33 | Multimap MAPPERS = HashMultimap.create(); 34 | 35 | /** 36 | * @param blockID The old block id. Useful for remapped blocks. 37 | * @param blockMetadata The block metadata. 38 | * @return A pair of [an optional new metadata value for the block, and the FluidState]. 39 | * To remap a block, use Forge's {@link net.minecraftforge.event.RegistryEvent.MissingMappings MissingMappings} event. 40 | * If you want to map a block that was remapped: cache its 41 | * {@link net.minecraftforge.event.RegistryEvent.MissingMappings.Mapping#id old ID} and compare it with the blockID 42 | * provided, and use the new block as the key for the {@link IFluidloggedDataMapper#MAPPERS} entry. 43 | * 44 | * @since 3.0.0 45 | * @author jbred 46 | */ 47 | @Nullable 48 | FluidMappingData remapFluidData(final int blockID, final int blockMetadata); 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/event/FluidloggableEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.event; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import git.jbredwards.fluidlogged_api.api.world.IWorldProvider; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.IBlockAccess; 13 | import net.minecraft.world.World; 14 | import net.minecraftforge.fluids.Fluid; 15 | import net.minecraftforge.fml.common.eventhandler.Cancelable; 16 | import net.minecraftforge.fml.common.eventhandler.Event; 17 | 18 | import javax.annotation.Nonnull; 19 | import javax.annotation.Nullable; 20 | 21 | /** 22 | * This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}, through 23 | * {@link git.jbredwards.fluidlogged_api.api.fluid.IFluidloggableFluid#isStateFluidloggable IFluidloggableFluid.isStateFluidloggable()}. 24 | * For modded blocks it's recommended to implement {@link git.jbredwards.fluidlogged_api.api.block.IFluidloggable IFluidloggable} 25 | * instead of using this event, as it also provides more functionality.
26 | *
27 | * This event is {@link Cancelable cancelable}.
28 | * This event has a {@link HasResult result}: 29 | *
  • {@link Result#ALLOW} means that the state is fluidloggable.
  • 30 | *
  • {@link Result#DEFAULT} means that {@link git.jbredwards.fluidlogged_api.api.block.IFluidloggable IFluidloggable} will be checked.
  • 31 | *
  • {@link Result#DENY} means that the state is not fluidloggable.
  • 32 | * 33 | * @since 1.9.0 34 | * @author jbred 35 | * 36 | */ 37 | @Cancelable 38 | @Event.HasResult 39 | public class FluidloggableEvent extends Event 40 | { 41 | @Nonnull public final IBlockState state; 42 | @Nonnull public final BlockPos pos; 43 | @Deprecated 44 | @Nonnull public final World world; // deprecated since 3.0.0 45 | @Nonnull public final IBlockAccess access; // since 3.0.0 46 | 47 | @Nullable public final Fluid fluid; 48 | @Nonnull public final FluidState fluidState; // since 3.0.0 49 | 50 | public FluidloggableEvent(@Nonnull final IBlockState stateIn, @Nonnull final IBlockAccess accessIn, @Nonnull final BlockPos posIn, @Nonnull final FluidState fluidStateIn) { 51 | state = stateIn; 52 | pos = posIn; 53 | 54 | fluidState = fluidStateIn; 55 | fluid = fluidStateIn.getFluid(); 56 | 57 | access = accessIn; 58 | world = IWorldProvider.getWorld(accessIn); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/fluid/ICompatibleFluid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.fluid; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 9 | import net.minecraftforge.fluids.Fluid; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * Have your fluid (not fluid block) implement this if it should treat other fluids as "equal". See 15 | * issue#44 for more info. 16 | *

    Use {@link net.minecraftforge.fml.common.Optional Forge's Optional @interfaces} to prevent a required Fluidlogged API dependency.

    17 | * 18 | * @since 1.7.0 19 | * @author jbred 20 | * 21 | */ 22 | public interface ICompatibleFluid 23 | { 24 | /** 25 | * Allows cross-mod compatibility with no dependencies 26 | * (example, water-like fluids would return FluidRegistry.WATER) 27 | * 28 | * @since 1.8.0 29 | * @author jbred 30 | */ 31 | @Nonnull 32 | Fluid getParentFluid(); 33 | 34 | /** 35 | * Called by {@link ICompatibleFluid#getFluidCompatibility}, 36 | * which is invoked a lot, so try to keep the code for this fairly light. 37 | * 38 | * @param otherFluid Fluid to compare with this one. 39 | * @return True if this fluid is compatible with otherFluid. 40 | * @throws NullPointerException If otherFluid is null. 41 | * 42 | * @since 1.8.0 43 | * @author jbred 44 | */ 45 | default boolean isCompatibleFluid(@Nonnull final Fluid otherFluid) { 46 | // use recursion by default in case the parent & otherFluid are compatible 47 | // ie every fluid doesn't have to have hardcoded compat 48 | return FluidloggedUtils.isCompatibleFluid(getParentFluid(), otherFluid); 49 | } 50 | 51 | /** 52 | * Called by {@link FluidloggedUtils#isCompatibleFluid}, 53 | * which is invoked a lot, so try to keep the code for this fairly light. 54 | * 55 | * @param otherFluid Fluid to compare with this one. 56 | * @return A number > 0 to specify fluid compatibility, or a number <= 0 to specify incompatibility. 57 | * If otherFluid is also an instance of ICompatibleFluid, 58 | *
    {@code
    59 |      * final int compat1 = ((ICompatibleFluid)fluid1).getFluidCompatibility(fluid2);
    60 |      * final int compat2 = ((ICompatibleFluid)fluid2).getFluidCompatibility(fluid1);
    61 |      * return Math.max(compat1, compat2) - Math.min(compat1, compat2);
    62 |      * }
    63 | * is used instead. 64 | * 65 | * @throws NullPointerException If otherFluid is null. 66 | * @since 3.0.0 67 | * @author jbred 68 | */ 69 | default int getFluidCompatibility(@Nonnull final Fluid otherFluid) { return isCompatibleFluid(otherFluid) ? 1 : 0; } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/fluid/IFlowCostFluid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.fluid; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import net.minecraft.world.World; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * Have your fluid block implement this if it should have a flow cost that isn't 1. 15 | * 16 | * @since 3.0.0 17 | * @author jbred 18 | * 19 | */ 20 | public interface IFlowCostFluid 21 | { 22 | /** 23 | * The flow cost of a fluid is the amount of {@link net.minecraft.block.BlockLiquid#LEVEL levels} that fluid blocks lose the further it is from its source block (or from a waterfall). 24 | * For example, water has a flow cost of 1, and lava has a flow cost of 2 (or in the nether, lava has a flow cost of 1). 25 | *

    26 | * The flow cost for any fluid block must be a factor of its {@link net.minecraftforge.fluids.BlockFluidBase#quantaPerBlock quantaPerBlock}. 27 | *

    28 | * 29 | * @param fluidState FluidState. 30 | * @param world World. 31 | * @return The flow cost for this fluid block. 32 | * @throws NullPointerException If fluidState or world are null. 33 | * 34 | * @since 3.0.0 35 | * @author jbred 36 | */ 37 | int getFlowCost(@Nonnull final FluidState fluidState, @Nonnull final World world); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/network/message/AbstractMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.network.message; 7 | 8 | import io.netty.buffer.ByteBuf; 9 | import net.minecraft.network.PacketBuffer; 10 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 11 | 12 | import javax.annotation.Nonnull; 13 | 14 | /** 15 | * An IMessage base class that uses PacketBuffer and has "isValid" checks built-in. 16 | * @since 1.9.0 17 | * @author jbred 18 | * 19 | */ 20 | public abstract class AbstractMessage implements IMessage 21 | { 22 | /** 23 | * Controls whether this message is written to the buffer and handled by the 24 | * {@link net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler IMessageHandler}. 25 | * This value should be set to true in your message's non-empty constructor only. 26 | * @since 1.9.0 27 | */ 28 | public boolean isValid; 29 | 30 | /** 31 | * Convert from the supplied buffer into this specific message type if the message is valid. 32 | * 33 | * @param buf The byte buffer. 34 | * @throws NullPointerException If buf is null. 35 | * 36 | * @since 1.9.0 37 | * @author jbred 38 | */ 39 | @Override 40 | public final void fromBytes(@Nonnull final ByteBuf buf) { 41 | isValid = buf.readBoolean(); 42 | if(isValid) read(new PacketBuffer(buf)); 43 | } 44 | 45 | /** 46 | * Deconstructs this message into the supplied byte buffer if this message is valid. 47 | * 48 | * @param buf The byte buffer. 49 | * @throws NullPointerException If buf is null. 50 | * 51 | * @since 1.9.0 52 | * @author jbred 53 | */ 54 | @Override 55 | public final void toBytes(@Nonnull final ByteBuf buf) { 56 | buf.writeBoolean(isValid); 57 | if(isValid) write(new PacketBuffer(buf)); 58 | } 59 | 60 | /** 61 | * Convert from the supplied packet buffer into your specific message type. 62 | * 63 | * @param buf The packet buffer. 64 | * @throws NullPointerException If buf is null. 65 | * 66 | * @since 1.9.0.3 67 | * @author jbred 68 | */ 69 | public abstract void read(@Nonnull final PacketBuffer buf); 70 | 71 | /** 72 | * Deconstructs your message into the supplied packet buffer. 73 | * 74 | * @param buf The packet buffer. 75 | * @throws NullPointerException If buf is null. 76 | * 77 | * @since 1.9.0.3 78 | * @author jbred 79 | */ 80 | public abstract void write(@Nonnull final PacketBuffer buf); 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/world/IChunkProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.world; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import net.minecraft.util.math.Vec3i; 10 | import net.minecraft.world.chunk.Chunk; 11 | 12 | import javax.annotation.Nonnull; 13 | import javax.annotation.Nullable; 14 | 15 | /** 16 | * Gives IBlockAccess instances the option to provide chunks in a way that this mod can access them. 17 | *

    18 | * {@link net.minecraft.world.World World} and {@link net.minecraft.world.ChunkCache ChunkCache} implement this at runtime, along with some modded classes. 19 | * 20 | * @since 3.0.0 21 | * @author jbred 22 | * 23 | */ 24 | public interface IChunkProvider extends IFluidStateProvider 25 | { 26 | /** 27 | * @param chunkX X position of the chunk (chunk coords, not block coords). 28 | * @param chunkZ Z position of the chunk (chunk coords, not block coords). 29 | * @return The chunk at the position. 30 | * 31 | * @since 3.0.0 32 | * @author jbred 33 | */ 34 | @Nullable 35 | Chunk getChunk(final int chunkX, final int chunkZ); 36 | 37 | /** 38 | * @param pos Position. 39 | * @return The chunk at the position. 40 | * @throws NullPointerException If pos is null. 41 | * 42 | * @since 3.0.0 43 | * @author jbred 44 | */ 45 | @Nullable 46 | default Chunk getChunk(@Nonnull final Vec3i pos) { return getChunk(pos.getX() >> 4, pos.getZ() >> 4); } 47 | 48 | /** 49 | * @param x X position. 50 | * @param y Y position. 51 | * @param z Z position. 52 | * @return The fluid state at the position, or {@link FluidState#EMPTY} if none is present. 53 | * 54 | * @since 3.0.0 55 | * @author jbred 56 | */ 57 | @Nonnull 58 | @Override 59 | default FluidState getFluidState(final int x, final int y, final int z) { 60 | return FluidState.getFromProvider(getChunk(x >> 4, z >> 4), x, y, z); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/world/IFluidStateProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.world; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import net.minecraft.util.math.Vec3i; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * Gives IBlockAccess instances the option to provide FluidStates in a way that this mod can access them. 15 | * If your IBlockAccess instance can provide chunks, implement {@link IChunkProvider} instead. 16 | *

    17 | * {@link net.minecraft.world.World World} and {@link net.minecraft.world.ChunkCache ChunkCache} implement this at runtime, along with some modded classes. 18 | * 19 | * @since 3.0.0 20 | * @author jbred 21 | * 22 | */ 23 | public interface IFluidStateProvider 24 | { 25 | /** 26 | * @param x X position. 27 | * @param y Y position. 28 | * @param z Z position. 29 | * @return The fluid state at the position, or {@link FluidState#EMPTY} if none is present. 30 | * 31 | * @since 3.0.0 32 | * @author jbred 33 | */ 34 | @Nonnull 35 | FluidState getFluidState(final int x, final int y, final int z); 36 | 37 | /** 38 | * @param pos Position. 39 | * @return The fluid state at the position, or {@link FluidState#EMPTY} if none is present. 40 | * @throws NullPointerException If pos is null. 41 | * 42 | * @since 3.0.0 43 | * @author jbred 44 | */ 45 | @Nonnull 46 | default FluidState getFluidState(@Nonnull final Vec3i pos) { 47 | return getFluidState(pos.getX(), pos.getY(), pos.getZ()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/api/world/IWorldChunkProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.api.world; 7 | 8 | import net.minecraft.world.chunk.Chunk; 9 | 10 | import javax.annotation.Nullable; 11 | 12 | /** 13 | * A convenience interface that extends both {@link IChunkProvider} and {@link IWorldProvider}. 14 | * 15 | * @since 3.0.0 16 | * @author jbred 17 | * 18 | */ 19 | public interface IWorldChunkProvider extends IChunkProvider, IWorldProvider 20 | { 21 | /** 22 | * @param chunkX X position of the chunk (chunk coords, not block coords). 23 | * @param chunkZ Z position of the chunk (chunk coords, not block coords). 24 | * @return The chunk at the position. 25 | * 26 | * @since 3.0.0 27 | * @author jbred 28 | */ 29 | @Nullable 30 | @Override 31 | default Chunk getChunk(final int chunkX, final int chunkZ) { return getWorld().getChunk(chunkX, chunkZ); } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/ICanFluidFlowHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import net.minecraft.block.state.BlockStateBase; 9 | import net.minecraft.block.state.IBlockState; 10 | import net.minecraft.util.EnumFacing; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.IBlockAccess; 13 | import net.minecraftforge.common.property.IExtendedBlockState; 14 | 15 | import javax.annotation.Nonnull; 16 | import javax.annotation.Nullable; 17 | 18 | /** 19 | * Accessor implemented by {@link BlockStateBase} at runtime to allow for config-based canFluidFlow interactions. 20 | * @author jbred 21 | * 22 | */ 23 | //TODO crafttweaker/groovyscript support maybe? 24 | @FunctionalInterface 25 | public interface ICanFluidFlowHandler 26 | { 27 | @Nonnull 28 | ICanFluidFlowHandler 29 | ALWAYS_FLOW = (world, pos, state, side) -> true, 30 | NEVER_FLOW = (world, pos, state, side) -> false, 31 | DEPRECATED_CHECK = (world, pos, state, side) -> !state.isSideSolid(world, pos, side); 32 | 33 | @Nonnull 34 | default ICanFluidFlowHandler negate() { return (world, pos, state, side) -> !canFluidFlow(world, pos, state, side); } 35 | boolean canFluidFlow(@Nonnull IBlockAccess world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull EnumFacing side); 36 | 37 | //Intended use only by config, implement IFluidloggable for custom modded canFluidFlow interactions. 38 | interface Accessor 39 | { 40 | @Nullable ICanFluidFlowHandler getCanFluidFlowOverride(); 41 | @Nullable static ICanFluidFlowHandler getOverride(@Nonnull IBlockState state) { 42 | if(state instanceof IExtendedBlockState) state = ((IExtendedBlockState)state).getClean(); 43 | return ((Accessor)state).getCanFluidFlowOverride(); 44 | } 45 | 46 | void setCanFluidFlowOverride(@Nullable ICanFluidFlowHandler override); 47 | static void setOverride(@Nonnull Object state, @Nullable ICanFluidFlowHandler override) { 48 | if(state instanceof IExtendedBlockState) state = ((IExtendedBlockState)state).getClean(); 49 | ((Accessor)state).setCanFluidFlowOverride(override); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IConditionalFluid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import net.minecraft.util.math.BlockPos; 10 | import net.minecraft.world.IBlockAccess; 11 | import net.minecraftforge.fluids.IFluidBlock; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * Allows thermal foundation's fluid flow limitation behavior to be added to fluidlogged api. 17 | * @author jbred 18 | * 19 | */ 20 | public interface IConditionalFluid extends IFluidBlock 21 | { 22 | boolean cannotFlowAt(@Nonnull final IBlockAccess world, @Nonnull final BlockPos pos, @Nonnull final FluidState fluidState); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IConfigAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import git.jbredwards.fluidlogged_api.mod.common.config.util.ConfigPredicate; 9 | import net.minecraft.block.state.BlockStateBase; 10 | 11 | import javax.annotation.Nonnull; 12 | import javax.annotation.Nullable; 13 | import java.util.HashSet; 14 | import java.util.Set; 15 | 16 | /** 17 | * Accessor implemented by {@link BlockStateBase} at runtime to allow for config-based fluidlogging interactions. 18 | * @author jbred 19 | * 20 | */ 21 | public interface IConfigAccessor 22 | { 23 | @Nullable 24 | ConfigPredicate getBlacklistPredicate(); 25 | void setBlacklistPredicate(@Nullable final ConfigPredicate predicate); 26 | 27 | @Nullable 28 | ConfigPredicate getWhitelistPredicate(); 29 | void setWhitelistPredicate(@Nullable final ConfigPredicate predicate); 30 | 31 | /** 32 | * Stores all IBlockStates that have a blacklist config predicate entry, so they can be reset prior to any config reloads. 33 | */ 34 | @Nonnull Set BLACKLIST_CACHE = new HashSet<>(); 35 | static void setBlacklistAndCache(@Nonnull final IConfigAccessor state, @Nullable final ConfigPredicate predicate) { 36 | state.setBlacklistPredicate(predicate); 37 | if(predicate != null) BLACKLIST_CACHE.add(state); 38 | } 39 | 40 | /** 41 | * Stores all IBlockStates that have a whitelist config predicate entry, so they can be reset prior to any config reloads. 42 | */ 43 | @Nonnull Set WHITELIST_CACHE = new HashSet<>(); 44 | static void setWhitelistAndCache(@Nonnull final IConfigAccessor state, @Nullable final ConfigPredicate predicate) { 45 | state.setWhitelistPredicate(predicate); 46 | if(predicate != null) WHITELIST_CACHE.add(state); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IConfigFluidBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import net.minecraft.block.state.IBlockState; 9 | import net.minecraftforge.common.property.IExtendedBlockState; 10 | 11 | import javax.annotation.Nonnull; 12 | import javax.annotation.Nullable; 13 | import java.util.List; 14 | 15 | /** 16 | * 17 | * @author jbred 18 | * 19 | */ 20 | public interface IConfigFluidBox 21 | { 22 | @Nonnull 23 | static IConfigFluidBox get(@Nonnull final IBlockState state) { 24 | return (IConfigFluidBox)(state instanceof IExtendedBlockState ? ((IExtendedBlockState)state).getClean() : state); 25 | } 26 | 27 | @Nullable 28 | List getBoxes(); 29 | void setBoxes(@Nullable final List boxes); 30 | final class HeightBox 31 | { 32 | public final double min, max; 33 | public HeightBox(final double minIn, final double maxIn) { 34 | min = minIn; 35 | max = maxIn; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IDefaultFluidState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import net.minecraft.block.state.IBlockState; 10 | 11 | import javax.annotation.Nonnull; 12 | import javax.annotation.Nullable; 13 | 14 | /** 15 | * Implemented by {@link net.minecraft.block.state.BlockStateBase BlockStateBase} at runtime to store a default FluidState 16 | * @author jbred 17 | * 18 | */ 19 | public interface IDefaultFluidState 20 | { 21 | @Nullable 22 | FluidState getDefaultFluidState(); 23 | void setDefaultFluidState(@Nullable final FluidState fluidState); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IHardcodedCapability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import git.jbredwards.fluidlogged_api.api.capability.IFluidStateCapability; 9 | 10 | import javax.annotation.Nonnull; 11 | 12 | /** 13 | * Implemented by {@link net.minecraft.world.chunk.Chunk Chunk} to greatly improve performance 14 | * @author jbred 15 | * 16 | */ 17 | public interface IHardcodedCapability 18 | { 19 | @Nonnull 20 | IFluidStateCapability getFluidStateCapability(); 21 | void setFluidStateCapability(@Nonnull final IFluidStateCapability cap); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/ILevelFluidStateLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | 10 | import javax.annotation.Nullable; 11 | 12 | /** 13 | * Implemented by {@link net.minecraft.block.state.BlockStateContainer BlockStateContainer} at runtime to store a leve-to-FluidState lookup array 14 | * @author jbred 15 | * 16 | */ 17 | public interface ILevelFluidStateLookup 18 | { 19 | @Nullable 20 | FluidState[][] getFluidStateLookup(); 21 | void setFluidStateLookup(@Nullable final FluidState[][] fluidStates); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IModdedWall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | /** 9 | * Applied to many improperly coded modded wall blocks, so they can all be easily made fluidloggable. 10 | * @author jbred 11 | * 12 | */ 13 | public interface IModdedWall {} 14 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/iface/IWaterHeight.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.iface; 7 | 8 | import javax.annotation.Nullable; 9 | 10 | /** 11 | * 12 | * @author jbred 13 | * 14 | */ 15 | public interface IWaterHeight 16 | { 17 | @Nullable 18 | IConfigFluidBox.HeightBox getBox(); 19 | void setBox(@Nullable final IConfigFluidBox.HeightBox waterHeight); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/forge/PluginFluidWater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.forge; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import net.minecraft.util.math.BlockPos; 10 | import net.minecraft.world.World; 11 | import net.minecraft.world.biome.BiomeColorHelper; 12 | import org.objectweb.asm.tree.ClassNode; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * add water's biome colors to its fluid class 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginFluidWater implements IASMPlugin 22 | { 23 | @Override 24 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 25 | /* 26 | * New code: 27 | * //use biome here if server, or biome blend if client 28 | * @ASMGenerated 29 | * public int getColor(World world, BlockPos pos) 30 | * { 31 | * return Hooks.getWaterColorAt(world, pos); 32 | * } 33 | */ 34 | addMethod(classNode, "getColor", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)I", 35 | "getWaterColorAt", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)I", generator -> { 36 | generator.visitVarInsn(ALOAD, 1); 37 | generator.visitVarInsn(ALOAD, 2); 38 | } 39 | ); 40 | 41 | return false; 42 | } 43 | 44 | @SuppressWarnings("unused") 45 | public static final class Hooks 46 | { 47 | public static int getWaterColorAt(@Nonnull World world, @Nonnull BlockPos pos) { 48 | return world.isRemote ? BiomeColorHelper.getWaterColorAtPos(world, pos) : world.getBiome(pos).getWaterColorMultiplier(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/forge/PluginForgeHooks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.forge; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fix ForgeHooks#isInsideOfMaterial by allowing it to access stored fluid blocks 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginForgeHooks implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("isInsideOfMaterial"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * isInsideOfMaterial: (changes are around line 1034) 27 | * Old code: 28 | * IBlockState state = entity.world.getBlockState(pos); 29 | * 30 | * New code: 31 | * //allow FluidStates to be used 32 | * IBlockState state = FluidloggedUtils.getFluidOrReal(entity.world, pos); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 36 | instructions.remove(insn); 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/appliedenergistics2/PluginAE2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.appliedenergistics2; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.MethodNode; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * make ae2's fluix crystal creation and crystal seed growth FluidState-sensitive 17 | * @author jbred 18 | * 19 | */ 20 | public final class PluginAE2 implements IASMPlugin 21 | { 22 | @Override 23 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(obfuscated ? "func_70071_h_" : "onUpdate"); } 24 | 25 | @Override 26 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 27 | /* 28 | * onUpdate: 29 | * Old code: 30 | * IBlockState state = this.world.getBlockState(new BlockPos(j, i, k)); 31 | * 32 | * New code: 33 | * // account for FluidStates 34 | * IBlockState state = FluidloggedUtils.getFluidOrReal(this.world, new BlockPos(j, i, k)); 35 | */ 36 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 37 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 38 | instructions.remove(insn); 39 | return true; 40 | } 41 | 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/astral_sorcery/PluginAstralSorceryAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.astral_sorcery; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * make astral sorcery's block access wrappers FluidState-sensitive 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginAstralSorceryAccess implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | // make these clientside only classes actually clientside, so the game crashes if other mods use them serverside 23 | classNode.visitAnnotation("Lnet/minecraftforge/fml/relauncher/SideOnly;", true).visitEnum("value", "Lnet/minecraftforge/fml/relauncher/Side;", "CLIENT"); 24 | // astral sorcery structures don't use FluidStates, so all of these are empty 25 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/world/IWorldProvider"); 26 | addMethod(classNode, "getChunk", "(II)Lnet/minecraft/world/chunk/Chunk;", null, null, generator -> 27 | generator.visitInsn(ACONST_NULL)); 28 | addMethod(classNode, "getFluidState", "(III)Lgit/jbredwards/fluidlogged_api/api/util/FluidState;", null, null, generator -> 29 | generator.visitFieldInsn(GETSTATIC, "git/jbredwards/fluidlogged_api/api/util/FluidState", "EMPTY", "Lgit/jbredwards/fluidlogged_api/api/util/FluidState;")); 30 | addMethod(classNode, "getWorld", "()Lnet/minecraft/world/World;", null, null, generator -> { 31 | generator.visitMethodInsn(INVOKESTATIC, "net/minecraftforge/fml/client/FMLClientHandler", "instance", "()Lnet/minecraftforge/fml/client/FMLClientHandler;", false); 32 | generator.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/fml/client/FMLClientHandler", "getWorldClient", "()Lnet/minecraft/client/multiplayer/WorldClient;", false); 33 | }); 34 | return false; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/betweenlands/PluginBetweenlandsRubber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.betweenlands; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.common.fluid.handler.FluidCollisionHandler; 10 | import net.minecraft.block.material.Material; 11 | import net.minecraft.block.state.IBlockState; 12 | import net.minecraft.entity.Entity; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.world.IBlockAccess; 15 | import org.objectweb.asm.tree.ClassNode; 16 | 17 | import javax.annotation.Nonnull; 18 | import javax.annotation.Nullable; 19 | 20 | /** 21 | * fix fluid collisions 22 | * @author jbred 23 | * 24 | */ 25 | public final class PluginBetweenlandsRubber implements IASMPlugin 26 | { 27 | @Override 28 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 29 | overrideMethod(classNode, method -> method.name.equals("isEntityInsideMaterial"), 30 | "isEntityInsideMaterial", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/entity/Entity;DLnet/minecraft/block/material/Material;Z)Ljava/lang/Boolean;", generator -> { 31 | generator.visitVarInsn(ALOAD, 1); 32 | generator.visitVarInsn(ALOAD, 2); 33 | generator.visitVarInsn(ALOAD, 3); 34 | generator.visitVarInsn(ALOAD, 4); 35 | generator.visitVarInsn(DLOAD, 5); 36 | generator.visitVarInsn(ALOAD, 7); 37 | generator.visitVarInsn(ILOAD, 8); 38 | } 39 | ); 40 | 41 | return false; 42 | } 43 | 44 | @SuppressWarnings("unused") 45 | public static final class Hooks 46 | { 47 | @Nullable 48 | public static Boolean isEntityInsideMaterial(@Nonnull final IBlockAccess world, @Nonnull final BlockPos blockpos, @Nonnull final IBlockState iblockstate, @Nonnull final Entity entity, final double yToTest, @Nonnull final Material materialIn, final boolean testingHead) { 49 | return FluidCollisionHandler.isEntityInsideMaterial(world, blockpos, iblockstate, entity, yToTest, materialIn == Material.WATER ? iblockstate.getMaterial() : materialIn, testingHead); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/betweenlands/PluginBetweenlandsTarBeast.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.betweenlands; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * tar beast cannot be pushed by fluids 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginBetweenlandsTarBeast implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | addMethod(classNode, obfuscated ? "func_96092_aw" : "isPushedByWater", "()Z", null, null, generator -> generator.visitInsn(ICONST_0)); 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/biomesoplenty/PluginBucketEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.biomesoplenty; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * remove unnecessary event handler for BOP fluid bucket filling (and fixes a honey fluid dupe) 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginBucketEventHandler implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | overrideMethod(classNode, method -> method.name.equals("onRightClickHoldingBucket"), null, null, generator -> {}); 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/botania/PluginGardenOfGlass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.botania; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * wooden bowls can now be filled by using water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginGardenOfGlass implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("onPlayerInteract"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * onPlayerInteract: 27 | * Old code: 28 | * if (event.getWorld().getBlockState(rtr.getBlockPos()).getMaterial() == Material.WATER) 29 | * { 30 | * ... 31 | * } 32 | * 33 | * New code: 34 | * // wooden bowls can now be filled by using water FluidStates 35 | * if (FluidloggedUtils.isCompatibleFluid(FluidloggedUtils.getFluidState(event.getWorld(), rtr.getBlockPos()).getFluid(), FluidRegistry.WATER)) 36 | * { 37 | * ... 38 | * } 39 | */ 40 | if(checkMethod(insn.getNext(), obfuscated ? "func_185904_a" : "getMaterial")) { 41 | ((JumpInsnNode)getNext(insn, 3)).setOpcode(IFEQ); 42 | final InsnList list = new InsnList(); 43 | list.add(genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidState", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lgit/jbredwards/fluidlogged_api/api/util/FluidState;")); 44 | list.add(new MethodInsnNode(INVOKEVIRTUAL, "git/jbredwards/fluidlogged_api/api/util/FluidState", "getFluid", "()Lnet/minecraftforge/fluids/Fluid;", false)); 45 | list.add(new FieldInsnNode(GETSTATIC, "net/minecraftforge/fluids/FluidRegistry", "WATER", "Lnet/minecraftforge/fluids/Fluid;")); 46 | list.add(genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "isCompatibleFluid", "(Lnet/minecraftforge/fluids/Fluid;Lnet/minecraftforge/fluids/Fluid;)Z")); 47 | 48 | instructions.insertBefore(insn, list); 49 | removeFrom(instructions, insn, 2); 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/buildcraft/PluginTileFloodGate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.buildcraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.tileentity.TileEntity; 12 | import net.minecraft.util.math.BlockPos; 13 | import org.objectweb.asm.tree.AbstractInsnNode; 14 | import org.objectweb.asm.tree.InsnList; 15 | import org.objectweb.asm.tree.MethodNode; 16 | 17 | import javax.annotation.Nonnull; 18 | 19 | /** 20 | * make buildcraft's TileFloodGate FluidState-sensitive 21 | * @author jbred 22 | * 23 | */ 24 | public final class PluginTileFloodGate implements IASMPlugin 25 | { 26 | @Override 27 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("canFill"); } 28 | 29 | @Override 30 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 31 | /* 32 | * canFill: 33 | * Old code: 34 | * this.getLocalState(offsetPos) 35 | * 36 | * New code: 37 | * // account for FluidStates 38 | * Hooks.getFluidOrReal(this, offsetPos) 39 | */ 40 | if(checkMethod(insn, "getLocalState")) { 41 | instructions.insert(insn, genMethodNode("getFluidOrReal", "(Lnet/minecraft/tileentity/TileEntity;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 42 | removeFrom(instructions, insn, -1); 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | @SuppressWarnings("unused") 50 | public static final class Hooks 51 | { 52 | @Nonnull 53 | public static IBlockState getFluidOrReal(@Nonnull final TileEntity tile, @Nonnull final BlockPos pos) { 54 | return FluidloggedUtils.getFluidOrReal(tile.getWorld(), pos); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/buildcraft/PluginTilePump.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.buildcraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.MethodNode; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * make buildcraft's pump account for FluidStates when checking for an infinite water source 17 | * @author jbred 18 | * 19 | */ 20 | public final class PluginTilePump implements IASMPlugin 21 | { 22 | @Override 23 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("buildQueue0"); } 24 | 25 | @Override 26 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 27 | /* 28 | * buildQueue0: 29 | * Old code: 30 | * IBlockState below = world.getBlockState(posToCheck.down()); 31 | * 32 | * New code: 33 | * // account for FluidStates 34 | * IBlockState below = FluidloggedUtils.getFluidOrReal(world, posToCheck.down()); 35 | */ 36 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 37 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 38 | instructions.remove(insn); 39 | return true; 40 | } 41 | 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/chiseled_me/PluginChiseledMe.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.chiseled_me; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fix chiseled me conflict 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginChiseledMe implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 22 | //fluidlogged api already implements these patches 23 | classNode.methods.removeIf(method -> method.name.equals("rayTraceBlocks") || method.name.equals("isInLava")); 24 | return true; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/crafttweaker/PluginCraftTweaker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.crafttweaker; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * MCWorldBlock.getFluid can read FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginCraftTweaker implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("getFluid"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * getFluid: 27 | * Old code: 28 | * return CraftTweakerMC.getILiquidDefinition(FluidRegistry.lookupFluidForBlock(blocks.getBlockState(pos).getBlock())); 29 | * 30 | * New code: 31 | * allow CraftTweaker scripts to access FluidStates 32 | * return CraftTweakerMC.getILiquidDefinition(FluidloggedUtils.getFluidState(this.blocks, this.pos).getFluid()); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insertBefore(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidState", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lgit/jbredwards/fluidlogged_api/api/util/FluidState;")); 36 | instructions.insertBefore(insn, new MethodInsnNode(INVOKEVIRTUAL, "git/jbredwards/fluidlogged_api/api/util/FluidState", "getFluid", "()Lnet/minecraftforge/fluids/Fluid;", false)); 37 | removeFrom(instructions, insn, 2); 38 | return true; 39 | } 40 | 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/dynamictrees/PluginModelRootyWater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.dynamictrees; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * remove water model, as the water is now handled via fluidlogging 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginModelRootyWater implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | /* 23 | * New code: 24 | * // Remove water model, as the water is now handled via fluidlogging 25 | * @ASMOverwrite 26 | * public List getQuads(IBlockState state, EnumFacing side, long rand) 27 | * { 28 | * return this.rootsModel.getQuads(state, side, rand); 29 | * } 30 | */ 31 | overrideMethod(classNode, method -> method.name.equals(obfuscated ? "func_188616_a" : "getQuads"), null, null, generator -> { 32 | generator.visitVarInsn(ALOAD, 0); 33 | generator.visitFieldInsn(GETFIELD, "com/ferreusveritas/dynamictrees/models/ModelRootyWater", "rootsModel", "Lnet/minecraft/client/renderer/block/model/IBakedModel;"); 34 | generator.visitVarInsn(ALOAD, 1); 35 | generator.visitVarInsn(ALOAD, 2); 36 | generator.visitVarInsn(LLOAD, 3); 37 | generator.visitMethodInsn(INVOKEINTERFACE, "net/minecraft/client/renderer/block/model/IBakedModel", obfuscated ? "func_188616_a" : "getQuads", "(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/EnumFacing;J)Ljava/util/List;", true); 38 | }); 39 | /* 40 | * New code: 41 | * // Use root's particle texture instead of water 42 | * @ASMOverwrite 43 | * public TextureAtlasSprite getParticleTexture() 44 | * { 45 | * return this.rootsModel.getParticleTexture(); 46 | * } 47 | */ 48 | overrideMethod(classNode, method -> method.name.equals(obfuscated ? "func_177554_e" : "getParticleTexture"), null, null, generator -> { 49 | generator.visitVarInsn(ALOAD, 0); 50 | generator.visitFieldInsn(GETFIELD, "com/ferreusveritas/dynamictrees/models/ModelRootyWater", "rootsModel", "Lnet/minecraft/client/renderer/block/model/IBakedModel;"); 51 | generator.visitMethodInsn(INVOKEINTERFACE, "net/minecraft/client/renderer/block/model/IBakedModel", obfuscated ? "func_177554_e" : "getParticleTexture", "()Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;", true); 52 | }); 53 | 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/enderio/PluginEnderIOSponge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.enderio; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.MethodNode; 12 | import org.objectweb.asm.tree.VarInsnNode; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * make ender io's sponge (industrial insulation block) FluidState-sensitive 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginEnderIOSponge implements IASMPlugin 22 | { 23 | @Override 24 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("absorb"); } 25 | 26 | @Override 27 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 28 | /* 29 | * absorb: 30 | * Old code: 31 | * IBlockState state = worldIn.getBlockState(blockpos1); 32 | * 33 | * New code: 34 | * // account for FluidStates 35 | * IBlockState state = FluidloggedUtils.getFluidOrReal(worldIn, blockpos1); 36 | */ 37 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 38 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 39 | instructions.remove(insn); 40 | } 41 | /* 42 | * absorb: 43 | * Old code: 44 | * worldIn.setBlockState(pos.offset(dx, dy, dz), Blocks.AIR.getDefaultState(), 2); 45 | * 46 | * New code: 47 | * // account for FluidStates 48 | * PluginBlockSponge.Hooks.drain(worldIn, pos.offset(dx, dy, dz), 2, state); 49 | */ 50 | else if(checkMethod(insn, obfuscated ? "func_180501_a" : "setBlockState")) { 51 | removeFrom(instructions, getPrevious(insn, 2), -1); 52 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockSponge$Hooks", "drain", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;ILnet/minecraft/block/state/IBlockState;)Z")); 53 | instructions.insert(insn, new VarInsnNode(ALOAD, findLocal(method, "blockToCheck", "Lnet/minecraft/block/state/IBlockState;").index)); 54 | instructions.remove(insn); 55 | return true; 56 | } 57 | 58 | return false; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/extrautils/PluginExtraUtilsAccessDelegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.extrautils; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * extrautils' block access wrapper FluidState-sensitive 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginExtraUtilsAccessDelegate implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/world/IBlockAccessWrapper"); 23 | addMethod(classNode, "getWrapped", "()Lnet/minecraft/world/IBlockAccess;", null, null, generator -> { 24 | generator.visitVarInsn(ALOAD, 0); 25 | generator.visitFieldInsn(GETFIELD, "com/rwtema/extrautils2/utils/blockaccess/BlockAccessDelegate", "base", "Lnet/minecraft/world/IBlockAccess;"); 26 | }); 27 | 28 | return false; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/extrautils/PluginExtraUtilsAccessServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.extrautils; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * extrautils' block access wrapper FluidState-sensitive 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginExtraUtilsAccessServer implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/world/IBlockAccessWrapper"); 23 | addMethod(classNode, "getWrapped", "()Lnet/minecraft/world/IBlockAccess;", null, null, generator -> { 24 | generator.visitVarInsn(ALOAD, 0); 25 | generator.visitFieldInsn(GETFIELD, "com/rwtema/extrautils2/utils/blockaccess/ThreadSafeBlockAccess", "world", "Lnet/minecraft/world/WorldServer;"); 26 | }); 27 | /* 28 | * public Chunk getChunk(int chunkX, int chunkZ) 29 | * { 30 | * return (Chunk)this.chunkMap.get(ChunkPos.asLong(chunkX, chunkZ)); 31 | * } 32 | */ 33 | addMethod(classNode, "getChunk", "(II)Lnet/minecraft/world/chunk/Chunk;", null, null, generator -> { 34 | generator.visitVarInsn(ALOAD, 0); 35 | generator.visitFieldInsn(GETFIELD, "com/rwtema/extrautils2/utils/blockaccess/ThreadSafeBlockAccess", "chunkMap", "Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;"); 36 | generator.visitVarInsn(ILOAD, 1); 37 | generator.visitVarInsn(ILOAD, 2); 38 | generator.visitMethodInsn(INVOKESTATIC, "net/minecraft/util/math/ChunkPos", obfuscated ? "func_77272_a" : "asLong", "(II)J", false); 39 | generator.visitMethodInsn(INVOKEINTERFACE, "it/unimi/dsi/fastutil/longs/Long2ObjectMap", "get", "(J)Ljava/lang/Object;", true); 40 | generator.visitTypeInsn(CHECKCAST, "net/minecraft/world/chunk/Chunk"); 41 | }); 42 | 43 | return false; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/galacticraft/PluginGCBlocks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.galacticraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.MethodNode; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * don't register Galacticraft's water & lava grating blocks, so they can be remapped 17 | * @author jbred 18 | * 19 | */ 20 | public final class PluginGCBlocks implements IASMPlugin 21 | { 22 | @Override 23 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("registerBlocks"); } 24 | 25 | @Override 26 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 27 | /* 28 | * registerBlocks: 29 | * Old code: 30 | * registerBlock(gratingWater, (Class)null); 31 | * registerBlock(gratingLava, (Class)null); 32 | * 33 | * New code: 34 | * // don't register Galacticraft's water & lava grating blocks, so they can be remapped 35 | * ... 36 | * ... 37 | */ 38 | if(checkField(insn, "gratingWater")) removeFrom(instructions, insn, 2); 39 | else if(checkField(insn, "gratingLava")) { 40 | removeFrom(instructions, insn, 2); 41 | return true; 42 | } 43 | 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/industrial_renewal/PluginIndustrialRenewal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.industrial_renewal; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import net.minecraft.block.Block; 10 | import net.minecraft.util.math.BlockPos; 11 | import net.minecraft.world.IBlockAccess; 12 | import org.objectweb.asm.tree.*; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * Fix industrial renewal mod's multi-blocks 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginIndustrialRenewal implements IASMPlugin 22 | { 23 | @Override 24 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_176196_c" : "canPlaceBlockAt"); } 25 | 26 | @Override 27 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 28 | /* 29 | * canPlaceBlockAt: 30 | * Old code: 31 | * this.isReplaceable(worldIn, pos) 32 | * 33 | * New code: 34 | * //fix industrial renewal mod's multi-blocks 35 | * Hooks.isReplaceable(this, worldIn, pos) 36 | */ 37 | if(checkMethod(insn, obfuscated ? "func_176200_f" : "isReplaceable")) { 38 | instructions.insert(insn, genMethodNode("isReplaceable", "(Lnet/minecraft/block/Block;Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Z")); 39 | instructions.remove(insn); 40 | } 41 | 42 | return false; 43 | } 44 | 45 | @SuppressWarnings("unused") 46 | public static final class Hooks 47 | { 48 | public static boolean isReplaceable(@Nonnull Block unused, @Nonnull IBlockAccess world, @Nonnull BlockPos pos) { 49 | return world.getBlockState(pos).getBlock().isReplaceable(world, pos); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/lycanitesmobs/PluginLycanitesFluidBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.lycanitesmobs; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * remove isEntityInsideMaterial override 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginLycanitesFluidBase implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | classNode.methods.removeIf(method -> method.name.equals("isEntityInsideMaterial")); 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/lycanitesmobs/PluginLycanitesFluidSources.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.lycanitesmobs; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 10 | import git.jbredwards.fluidlogged_api.mod.common.fluid.handler.FluidMixHandler; 11 | import net.minecraft.init.Blocks; 12 | import net.minecraftforge.fluids.FluidRegistry; 13 | import org.objectweb.asm.tree.*; 14 | 15 | import javax.annotation.Nonnull; 16 | import java.util.Collection; 17 | import java.util.Collections; 18 | 19 | /** 20 | * fix lycanites fluid source logic 21 | * @author jbred 22 | * 23 | */ 24 | public final class PluginLycanitesFluidSources extends PluginLycanitesFluidMixing implements IASMPlugin 25 | { 26 | @Override 27 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(""); } 28 | 29 | @Override 30 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 31 | /* 32 | * Constructor: 33 | * Old code: 34 | * { 35 | * ... 36 | * } 37 | * 38 | * New code: 39 | * // Use forge fluid source creation logic 40 | * { 41 | * ... 42 | * this.canCreateSources = true; 43 | * } 44 | */ 45 | if(insn.getOpcode() == RETURN) { 46 | instructions.insertBefore(insn, new VarInsnNode(ALOAD, 0)); 47 | instructions.insertBefore(insn, new InsnNode(ICONST_1)); 48 | instructions.insertBefore(insn, new FieldInsnNode(PUTFIELD, "net/minecraftforge/fluids/BlockFluidClassic", "canCreateSources", "Z")); 49 | return true; 50 | } 51 | 52 | return false; 53 | } 54 | 55 | @Override 56 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 57 | if(classNode.name.endsWith("BlockFluidMoglava")) super.transformClass(classNode, obfuscated); 58 | return true; 59 | } 60 | 61 | @SuppressWarnings("unused") 62 | public static final class Hooks 63 | { 64 | @Nonnull 65 | public static Collection getMixConditions() { 66 | return Collections.singleton(FluidMixHandler.forFluid((source, access, pos, sourcePos, side) -> 67 | FluidloggedUtils.isCompatibleFluid(FluidloggedUtils.getFluidState(access, pos).getFluid(), FluidRegistry.WATER) ? Blocks.COBBLESTONE.getDefaultState() : null 68 | )); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/mekanism/PluginMekanismUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.mekanism; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * make mekanism's fluid getter methods FluidState-sensitive 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginMekanismUtils implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("getFluid") || method.name.equals("isDeadFluid"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 25 | /* 26 | * Old code: 27 | * IBlockState state = pos.getBlockState(world); 28 | * 29 | * New code: 30 | * // make mekanism's fluid getter methods FluidState-sensitive 31 | * IBlockState state = FluidloggedUtils.getFluidOrReal(world, pos.getPos()); 32 | */ 33 | if(checkMethod(insn, "getBlockState")) { 34 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 35 | instructions.insert(insn, new MethodInsnNode(INVOKEVIRTUAL, "mekanism/api/Coord4D", "getPos", "()Lnet/minecraft/util/math/BlockPos;", false)); 36 | instructions.insert(insn, new VarInsnNode(ALOAD, 1)); 37 | instructions.insert(insn, new VarInsnNode(ALOAD, 0)); 38 | removeFrom(instructions, insn, -2); 39 | return true; 40 | } 41 | 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/optifine/PluginOptifine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.optifine; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * better optifine compat 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginOptifine implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 22 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/world/IWorldProvider"); 23 | addMethod(classNode, "getWorld", "()Lnet/minecraft/world/World;", null, null, generator -> { 24 | generator.visitVarInsn(ALOAD, 0); 25 | generator.visitFieldInsn(GETFIELD, "net/optifine/override/ChunkCacheOF", "chunkCache", "Lnet/minecraft/world/ChunkCache;"); 26 | generator.visitMethodInsn(INVOKEVIRTUAL, "net/minecraft/world/ChunkCache", "getWorld", "()Lnet/minecraft/world/World;", false); 27 | }); 28 | /* 29 | * New code: 30 | * //allows optifine's ChunkCacheOF override to be compatible with this mod 31 | * @ASMGenerated 32 | * public Chunk getChunk(int chunkX, int chunkZ) 33 | * { 34 | * return this.chunkCache.getChunk(chunkX, chunkZ); 35 | * } 36 | */ 37 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/world/IChunkProvider"); 38 | addMethod(classNode, "getChunk", "(II)Lnet/minecraft/world/chunk/Chunk;", null, null, generator -> { 39 | generator.visitVarInsn(ALOAD, 0); 40 | generator.visitFieldInsn(GETFIELD, "net/optifine/override/ChunkCacheOF", "chunkCache", "Lnet/minecraft/world/ChunkCache;"); 41 | generator.visitVarInsn(ILOAD, 1); 42 | generator.visitVarInsn(ILOAD, 2); 43 | generator.visitMethodInsn(INVOKEVIRTUAL, "net/minecraft/world/ChunkCache", "getChunk", "(II)Lnet/minecraft/world/chunk/Chunk;", false); 44 | }); 45 | 46 | return false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/optifine/PluginSVertexBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.optifine; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import net.minecraft.block.BlockLiquid; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.util.EnumBlockRenderType; 12 | import org.objectweb.asm.tree.AbstractInsnNode; 13 | import org.objectweb.asm.tree.InsnList; 14 | import org.objectweb.asm.tree.MethodNode; 15 | import org.objectweb.asm.tree.VarInsnNode; 16 | 17 | import javax.annotation.Nonnull; 18 | 19 | /** 20 | * Set the block renderType (aka mc_Entity.y) to 1 if the block is a BlockLiquid 21 | * @author jbred 22 | * 23 | */ 24 | public final class PluginSVertexBuilder implements IASMPlugin 25 | { 26 | @Override 27 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return "pushEntity".equals(method.name); } 28 | 29 | @Override 30 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 31 | /* 32 | * pushEntity: 33 | * Old code: 34 | * int renderType = block.getRenderType(blockState).ordinal(); 35 | * 36 | * New code: 37 | * // tell Optifine to pass the old render type for BlockLiquid blocks into shaders 38 | * int renderType = Hooks.getRenderType(block.getRenderType(blockState), blockState).ordinal(); 39 | */ 40 | if(checkMethod(insn, obfuscated ? "func_149645_b" : "getRenderType")) { 41 | instructions.insert(insn, genMethodNode("getRenderType", "(Lnet/minecraft/util/EnumBlockRenderType;Lnet/minecraft/block/state/IBlockState;)Lnet/minecraft/util/EnumBlockRenderType;")); 42 | instructions.insert(insn, new VarInsnNode(ALOAD, 0)); 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | @SuppressWarnings("unused") 50 | public static final class Hooks 51 | { 52 | @Nonnull 53 | public static EnumBlockRenderType getRenderType(@Nonnull final EnumBlockRenderType oldType, @Nonnull final IBlockState state) { 54 | return state.getBlock() instanceof BlockLiquid ? EnumBlockRenderType.LIQUID : oldType; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/projectred/PluginProjectRed.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.projectred; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block.PluginBlockWall; 10 | import net.minecraft.util.math.BlockPos; 11 | import net.minecraft.world.World; 12 | import org.objectweb.asm.tree.*; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * allow wires to connect through fluids 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginProjectRed implements IASMPlugin 22 | { 23 | @Override 24 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("outsideCornerEdgeOpen"); } 25 | 26 | @Override 27 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 28 | /* 29 | * outsideCornerEdgeOpen: 30 | * Old code: (scala) 31 | * if (world.isAirBlock(pos)) true 32 | * 33 | * New code: (scala) 34 | * //allow wires to connect through fluids 35 | * if (Hooks.isAirOrFluid(world, pos)) true 36 | */ 37 | if(checkMethod(insn, obfuscated ? "func_175623_d" : "isAirBlock")) { 38 | instructions.insert(insn, genMethodNode("isAirOrFluid", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Z")); 39 | instructions.remove(insn); 40 | return true; 41 | } 42 | 43 | return false; 44 | } 45 | 46 | @SuppressWarnings("unused") 47 | public static final class Hooks 48 | { 49 | public static boolean isAirOrFluid(@Nonnull World world, @Nonnull BlockPos pos) { 50 | return PluginBlockWall.Hooks.isAirOrFluid(world, pos); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/railcraft/PluginRailcraft.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.railcraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fix railcraft uncraftable potion bug when collecting water bottles (issue#148) 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginRailcraft implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(""); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * Constructor: 27 | * Old code: 28 | * containerTable.put(Items.GLASS_BOTTLE.delegate, "water", Items.POTIONITEM.delegate); 29 | * 30 | * New code: 31 | * //remove water bottles from the containerTable 32 | * ... 33 | */ 34 | if(checkMethod(insn.getPrevious(), "put")) { 35 | removeFrom(instructions, insn, -8); 36 | return true; 37 | } 38 | 39 | return false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/random_things/PluginRandomThings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.random_things; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.MethodNode; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * make random things' ender buckets sensitive to FluidStates 17 | * @author jbred 18 | * 19 | */ 20 | public final class PluginRandomThings implements IASMPlugin 21 | { 22 | @Override 23 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(obfuscated ? "func_77659_a" : "onItemRightClick"); } 24 | 25 | @Override 26 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 27 | /* 28 | * onItemRightClick: 29 | * Old code: 30 | * IBlockState hitState = world.getBlockState(mop.getBlockPos()); 31 | * ... 32 | * IBlockState nextState = world.getBlockState(next); 33 | * 34 | * New code: 35 | * // Account for FluidStates 36 | * IBlockState hitState = FluidloggedUtils.getFluidOrReal(world, mop.getBlockPos()); 37 | * ... 38 | * IBlockState nextState = FluidloggedUtils.getFluidOrReal(world, next); 39 | */ 40 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 41 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 42 | instructions.remove(insn); 43 | } 44 | 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/sledgehammer/PluginSledgehammer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.sledgehammer; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * remove redundant transformer 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginSledgehammer implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 22 | classNode.methods.removeIf(method -> method.name.equals("onGetDepth")); 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/spongeforge/PluginSpongeForge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.spongeforge; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.world.PluginWorldServer; 10 | import org.objectweb.asm.tree.AbstractInsnNode; 11 | import org.objectweb.asm.tree.ClassNode; 12 | import org.objectweb.asm.tree.InsnList; 13 | import org.objectweb.asm.tree.MethodNode; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * spongeforge no longer mixins into conflicting methods 19 | * @author jbred 20 | * 21 | */ 22 | public final class PluginSpongeForge implements IASMPlugin 23 | { 24 | @Override 25 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 26 | classNode.methods.removeIf(method 27 | -> method.name.equals("spongeImpl$onEntityCollideWithBlockState") 28 | || method.name.equals("impl$CheckForLiquidMixing") 29 | || method.name.equals("impl$throwModifyForLavaToStone") 30 | || method.name.equals("impl$CheckEventsBeforeSpreadingFire") 31 | || method.name.equals("asyncLighting$onRelightChecksGetBlockState") 32 | || method.name.equals("onCheckDisplaceIfPreAlreadyCancelled")); 33 | 34 | return false; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tfc/PluginTFCBlockFluid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tfc; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * duplicate fluid logic isn't needed, and causes conflicts with this mod 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginTFCBlockFluid implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 22 | classNode.methods.removeIf(method -> 23 | method.name.equals(obfuscated ? "func_180650_b" : "updateTick") || 24 | method.name.equals("getOptimalFlowDirections") || 25 | method.name.equals("calculateFlowCost") || 26 | method.name.equals("flowIntoBlock") || 27 | method.name.equals("canFlowInto") || 28 | method.name.equals("canDisplace") || 29 | method.name.equals("getExtendedState") || 30 | method.name.equals("getFluidHeightForRender")); 31 | 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tfc/PluginTFCFluids.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tfc; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.fluid.ICompatibleFluid; 10 | import net.minecraft.util.ResourceLocation; 11 | import net.minecraftforge.fluids.Fluid; 12 | import net.minecraftforge.fluids.FluidRegistry; 13 | import org.objectweb.asm.tree.*; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * use ICompatibleFluid for water-like fluids 19 | * @author jbred 20 | * 21 | */ 22 | public final class PluginTFCFluids implements IASMPlugin 23 | { 24 | @Override 25 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("registerFluids"); } 26 | 27 | @Override 28 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 29 | /* 30 | * registerFluids: 31 | * Old code: 32 | * registerFluid(new Fluid(...)) 33 | * 34 | * New code: 35 | * //use ICompatibleFluid for water-like fluids 36 | * registerFluid(new TFCWaterFluid(...)) 37 | */ 38 | if(insn.getOpcode() == NEW) { 39 | ((TypeInsnNode)insn).desc = "git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tfc/PluginTFCFluids$TFCWaterFluid"; 40 | ((MethodInsnNode)getNext(insn, 6)).owner = "git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tfc/PluginTFCFluids$TFCWaterFluid"; 41 | return ((LdcInsnNode)getNext(insn, 2)).cst.equals("salt_water"); 42 | } 43 | 44 | return false; 45 | } 46 | 47 | @SuppressWarnings("unused") 48 | public static final class TFCWaterFluid extends Fluid implements ICompatibleFluid 49 | { 50 | public TFCWaterFluid(@Nonnull String fluidName, @Nonnull ResourceLocation still, @Nonnull ResourceLocation flowing, int color) { 51 | super(fluidName, still, flowing, color); 52 | } 53 | 54 | @Nonnull 55 | @Override 56 | public Fluid getParentFluid() { return FluidRegistry.WATER; } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/thermal_dynamics/PluginThermalDynamics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.thermal_dynamics; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fix block raytrace to ignore fluids 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginThermalDynamics implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("openGui"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * openGui: 27 | * Old code: 28 | * RayTraceResult movingObjectPosition = RayTracer.retrace(player); 29 | * 30 | * New code: 31 | * //don't stop the raytrace when it comes in contact with a fluid 32 | * RayTraceResult movingObjectPosition = RayTracer.retrace(player, false); 33 | */ 34 | if(checkMethod(insn, "retrace")) { 35 | //change method to one with a flexible `stopAtFluid` flag & set it to false 36 | ((MethodInsnNode)insn).desc = "(Lnet/minecraft/entity/player/EntityPlayer;Z)Lnet/minecraft/util/math/RayTraceResult;"; 37 | instructions.insertBefore(insn, new InsnNode(ICONST_0)); 38 | return true; 39 | } 40 | 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tropicraft/PluginTropicraftBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tropicraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.InsnNode; 12 | import org.objectweb.asm.tree.MethodNode; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * Account for FluidStates when collecting tropical water 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginTropicraftBucket implements IASMPlugin 22 | { 23 | @Override 24 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("handleBucketFillEvent"); } 25 | 26 | @Override 27 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 28 | /* 29 | * handleBucketFillEvent: 30 | * Old code: 31 | * IBlockState iblockstate = event.getWorld().getBlockState(pos); 32 | * 33 | * New code: 34 | * // account for FluidStates when collecting tropical water 35 | * IBlockState iblockstate = FluidloggedUtils.getFluidOrReal(event.getWorld(), pos); 36 | */ 37 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 38 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 39 | instructions.remove(insn); 40 | } 41 | /* 42 | * handleBucketFillEvent: 43 | * Old code: 44 | * event.getWorld().setBlockToAir(pos); 45 | * 46 | * New code: 47 | * // ensure that FluidStates are drained 48 | * FluidloggedUtils.setFluidToAir(event.getWorld(), pos, null, 3); 49 | */ 50 | else if(checkMethod(insn, obfuscated ? "func_175698_g" : "setBlockToAir")) { 51 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "setFluidToAir", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;I)Z")); 52 | instructions.insert(insn, new InsnNode(ICONST_3)); 53 | instructions.insert(insn, new InsnNode(ACONST_NULL)); 54 | instructions.remove(insn); 55 | return true; 56 | } 57 | 58 | return false; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tropicraft/PluginTropicraftFence.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tropicraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fixes for tropicraft fences 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginTropicraftFence implements IASMPlugin 19 | { 20 | @Override 21 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 22 | // remove methods that deal with the (now unused) "WATER" blockState property 23 | classNode.methods.removeIf(method 24 | -> method.name.equals(obfuscated ? "func_149688_o" : "getMaterial") 25 | || method.name.equals(obfuscated ? "func_176201_c" : "getMetaFromState") 26 | || method.name.equals(obfuscated ? "func_176203_a" : "getStateFromMeta") 27 | || method.name.equals(obfuscated ? "func_189540_a" : "neighborChanged") 28 | || method.name.equals(obfuscated ? "func_176213_c" : "onBlockAdded") 29 | || method.name.equals("canRenderInLayer") 30 | || method.name.equals("getStateForPlacement")); 31 | 32 | // make tropicraft fences override the "applyDefaults" setting, as they must be fluidloggable for world gen 33 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/block/IFluidloggable"); 34 | addMethod(classNode, "overrideApplyDefaultsSetting", "()Z", null, null, generator -> generator.visitInsn(ICONST_1)); 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tropicraft/PluginTropicraftFluid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tropicraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fix issue#183 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginTropicraftFluid implements IASMPlugin 19 | { 20 | public final boolean isBlock; 21 | public PluginTropicraftFluid(boolean isBlockIn) { isBlock = isBlockIn; } 22 | 23 | @Override 24 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 25 | if(isBlock) classNode.methods.removeIf(method -> method.name.equals(obfuscated ? "func_176197_a" : "modifyAcceleration")); 26 | else { 27 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/api/fluid/ICompatibleFluid"); 28 | addMethod(classNode, "getParentFluid", "()Lnet/minecraftforge/fluids/Fluid;", null, null, generator -> generator.visitFieldInsn(GETSTATIC, "net/minecraftforge/fluids/FluidRegistry", "WATER", "Lnet/minecraftforge/fluids/Fluid;")); 29 | } 30 | 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tropicraft/PluginTropicraftOverlays.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tropicraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * account for FluidStates and improved fluid collisions 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginTropicraftOverlays implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals("onBlockOverlay"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 25 | /* 26 | * onBlockOverlay: 27 | * Old code: 28 | * IBlockState atPos = event.getPlayer().getEntityWorld().getBlockState(blockpos); 29 | * 30 | * New code: 31 | * // account for FluidStates 32 | * IBlockState atPos = ActiveRenderInfo.getBlockStateAtEntityViewpoint(event.getPlayer().getEntityWorld(), event.getPlayer(), event.getRenderPartialTicks()); 33 | */ 34 | if(checkMethod(insn.getNext(), obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insertBefore(insn, new VarInsnNode(ALOAD, 1)); 36 | instructions.insertBefore(insn, new MethodInsnNode(INVOKEVIRTUAL, "net/minecraftforge/client/event/RenderBlockOverlayEvent", "getPlayer", "()Lnet/minecraft/entity/player/EntityPlayer;", false)); 37 | instructions.insertBefore(insn, new VarInsnNode(ALOAD, 1)); 38 | instructions.insertBefore(insn, new MethodInsnNode(INVOKEVIRTUAL, "net/minecraftforge/client/event/RenderBlockOverlayEvent", "getRenderPartialTicks", "()F", false)); 39 | instructions.insertBefore(insn, genMethodNode("net/minecraft/client/renderer/ActiveRenderInfo", obfuscated ? "func_186703_a" : "getBlockStateAtEntityViewpoint", "(Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;F)Lnet/minecraft/block/state/IBlockState;")); 40 | removeFrom(instructions, insn, 1); 41 | return true; 42 | } 43 | 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/tropicraft/PluginTropicraftSand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.tropicraft; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * account for FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginTropicraftSand implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(obfuscated ? "func_176221_a" : "getActualState"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 25 | /* 26 | * getActualState: 27 | * Old code: 28 | * IBlockState above = worldIn.getBlockState(pos.up()); 29 | * 30 | * New code: 31 | * // account for FluidStates 32 | * IBlockState above = FluidloggedUtils.getFluidOrReal(worldIn, pos.up()); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 36 | instructions.remove(insn); 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/twilight_forest/PluginTwilightForest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.twilight_forest; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block.PluginBlockLilyPad; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.World; 13 | import org.objectweb.asm.tree.AbstractInsnNode; 14 | import org.objectweb.asm.tree.InsnList; 15 | import org.objectweb.asm.tree.MethodNode; 16 | 17 | import javax.annotation.Nonnull; 18 | 19 | /** 20 | * 2x2 lily pads can be placed on certain water FluidStates 21 | * @author jbred 22 | * 23 | */ 24 | public final class PluginTwilightForest implements IASMPlugin 25 | { 26 | @Override 27 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_77659_a" : "onItemRightClick"); } 28 | 29 | @Override 30 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 31 | /* 32 | * onItemRightClick: 33 | * Old code: 34 | * IBlockState iblockstate = worldIn.getBlockState(pos.down()); 35 | * 36 | * New code: 37 | * //use the FluidState if the state below is less than 1 block tall 38 | * IBlockState iblockstate = Hooks.getFluidIfApplicable(worldIn, pos.down()); 39 | */ 40 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 41 | instructions.insert(insn, genMethodNode("getFluidIfApplicable", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 42 | instructions.remove(insn); 43 | } 44 | 45 | return false; 46 | } 47 | 48 | @SuppressWarnings("unused") 49 | public static final class Hooks 50 | { 51 | @Nonnull 52 | public static IBlockState getFluidIfApplicable(@Nonnull World world, @Nonnull BlockPos pos) { 53 | return PluginBlockLilyPad.Hooks.getFluidIfApplicable(world, pos); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/modded/waila/PluginWaila.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.waila; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.Type; 10 | import org.objectweb.asm.tree.*; 11 | 12 | import javax.annotation.Nonnull; 13 | 14 | /** 15 | * remove duplicate handlers for BlockLiquid 16 | * @author jbred 17 | * 18 | */ 19 | public final class PluginWaila implements IASMPlugin 20 | { 21 | @Override 22 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals("register"); } 23 | 24 | @Override 25 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 26 | /* 27 | * register: 28 | * Old code: 29 | * registrar.registerStackProvider(HUDHandlerFluids.INSTANCE, BlockLiquid.class); 30 | * registrar.registerHeadProvider(HUDHandlerFluids.INSTANCE, BlockLiquid.class); 31 | * registrar.registerTailProvider(HUDHandlerFluids.INSTANCE, BlockLiquid.class); 32 | * 33 | * New code: 34 | * //remove duplicate handlers for BlockLiquid 35 | * ... 36 | */ 37 | if(insn.getOpcode() == LDC && ((LdcInsnNode)insn).cst.equals(Type.getType("Lnet/minecraft/block/BlockLiquid;"))) { 38 | final boolean isDone = checkMethod(insn.getNext(), "registerTailProvider"); 39 | instructions.remove(insn.getNext()); 40 | removeFrom(instructions, insn, -3); 41 | return isDone; 42 | } 43 | 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockCocoa.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * breaking this block type no longer voids the possible FluidState here 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginBlockCocoa implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_176500_f" : "dropBlock"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * dropBlock: (changes are around line 164) 27 | * Old code: 28 | * worldIn.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); 29 | * 30 | * New code: 31 | * //when a block is removed by a player, set the FluidState here (if it's empty air is set) 32 | * worldIn.setBlockState(pos, FluidState.get(worldIn, pos).getState(), 3); 33 | */ 34 | if(checkField(insn, obfuscated ? "field_150350_a" : "AIR", "Lnet/minecraft/block/Block;")) { 35 | final InsnList list = new InsnList(); 36 | //parameters 37 | list.add(new VarInsnNode(ALOAD, 1)); 38 | list.add(new VarInsnNode(ALOAD, 2)); 39 | //adds new code 40 | list.add(genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidState", "get", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lgit/jbredwards/fluidlogged_api/api/util/FluidState;")); 41 | list.add(new MethodInsnNode(INVOKEVIRTUAL, "git/jbredwards/fluidlogged_api/api/util/FluidState", "getState", "()Lnet/minecraft/block/state/IBlockState;", false)); 42 | instructions.insertBefore(insn, list); 43 | removeFrom(instructions, insn, 1); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockDynamicLiquid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 10 | import git.jbredwards.fluidlogged_api.mod.common.fluid.handler.FluidFlowHandler; 11 | import net.minecraft.block.state.IBlockState; 12 | import net.minecraft.util.math.BlockPos; 13 | import net.minecraft.world.World; 14 | import org.objectweb.asm.tree.*; 15 | 16 | import javax.annotation.Nonnull; 17 | import java.util.Random; 18 | 19 | /** 20 | * fixes a bunch of liquid interactions while fluidlogged 21 | * @author jbred 22 | * 23 | */ 24 | public final class PluginBlockDynamicLiquid implements IASMPlugin 25 | { 26 | @Override 27 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 28 | /* 29 | * updateTick: 30 | * New code: 31 | * // Rewrite flow logic to work while fluidlogged 32 | * @ASMGenerated 33 | * public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) 34 | * { 35 | * Hooks.updateLiquidTick(worldIn, pos, state, rand); 36 | * } 37 | */ 38 | overrideMethod(classNode, method -> method.name.equals(obfuscated ? "func_180650_b" : "updateTick"), 39 | "updateLiquidTick", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;Ljava/util/Random;)V", generator -> { 40 | generator.visitVarInsn(ALOAD, 1); 41 | generator.visitVarInsn(ALOAD, 2); 42 | generator.visitVarInsn(ALOAD, 3); 43 | generator.visitVarInsn(ALOAD, 4); 44 | } 45 | ); 46 | 47 | return false; 48 | } 49 | 50 | @SuppressWarnings("unused") 51 | public static final class Hooks 52 | { 53 | public static void updateLiquidTick(@Nonnull final World world, @Nonnull final BlockPos pos, @Nonnull final IBlockState state, @Nonnull final Random rand) { 54 | FluidFlowHandler.updateDynamic(world, pos, FluidState.of(state), rand); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockFarmland.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * farmland blocks now recognise water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginBlockFarmland implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { 22 | switch(method.name) { 23 | case "func_176530_e": case "hasWater": case "hasLava": // Nethercraft compat 24 | return true; 25 | default: return false; 26 | } 27 | } 28 | 29 | @Override 30 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 31 | /* 32 | * hasWater: (changes are around line 119) 33 | * Old code: 34 | * if (worldIn.getBlockState(blockpos$mutableblockpos).getMaterial() == Material.WATER) 35 | * { 36 | * ... 37 | * } 38 | * 39 | * New code: 40 | * //check for fluidlogged blocks 41 | * if (FluidloggedUtils.getFluidOrReal(worldIn, blockpos$mutableblockpos).getMaterial() == Material.WATER) 42 | * { 43 | * ... 44 | * } 45 | */ 46 | //separate obfuscated check to resolve foamfix conflict 47 | if(obfuscated && checkMethod(insn, "func_180495_p") || checkMethod(insn, "getBlockState")) { 48 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 49 | instructions.remove(insn); 50 | } 51 | 52 | return false; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockLilyPad.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 9 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.World; 13 | import org.objectweb.asm.tree.*; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * lily pads can stay on certain water FluidStates 19 | * @author jbred 20 | * 21 | */ 22 | public final class PluginBlockLilyPad implements IASMPlugin 23 | { 24 | @Override 25 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { 26 | switch(method.name) { 27 | case "func_180671_f": case "canBlockStay": 28 | case "func_176196_c": case "canPlaceBlockAt": // More Planets compat 29 | return true; 30 | default: return false; 31 | } 32 | } 33 | 34 | @Override 35 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 36 | /* 37 | * canBlockStay: (changes are around line 67) 38 | * Old code: 39 | * IBlockState iblockstate = worldIn.getBlockState(pos.down()); 40 | * 41 | * New code: 42 | * //use the FluidState if the state below is less than 1 block tall 43 | * IBlockState iblockstate = Hooks.getFluidIfApplicable(worldIn, pos.down()); 44 | */ 45 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState", null)) { 46 | instructions.insert(insn, genMethodNode("getFluidIfApplicable", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 47 | instructions.remove(insn); 48 | return true; 49 | } 50 | 51 | return false; 52 | } 53 | 54 | @SuppressWarnings("unused") 55 | public static final class Hooks 56 | { 57 | @Nonnull 58 | public static IBlockState getFluidIfApplicable(@Nonnull World world, @Nonnull BlockPos pos) { 59 | final IBlockState state = world.getBlockState(pos); 60 | return state.getBoundingBox(world, pos).maxY < 1 ? 61 | FluidloggedUtils.getFluidOrReal(world, pos, state) : state; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockReed.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * sugar cane blocks now recognise water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginBlockReed implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_176196_c" : "canPlaceBlockAt"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * canPlaceBlockAt: (changes are around line 103) 27 | * Old code: 28 | * IBlockState iblockstate = worldIn.getBlockState(blockpos.offset(enumfacing)); 29 | * 30 | * New code: 31 | * //check for FluidState 32 | * IBlockState iblockstate = FluidloggedUtils.getFluidOrReal(worldIn, blockpos.offset(enumfacing)); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState") && checkMethod(insn.getPrevious(), obfuscated ? "func_177972_a" : "offset")) { 35 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 36 | instructions.remove(insn); 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockSkull.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * wither skulls no longer void the FluidState here when summoning the wither 15 | * lots of people totally knew this was a problem, trust me ;) 16 | * @author jbred 17 | * 18 | */ 19 | public final class PluginBlockSkull implements IASMPlugin 20 | { 21 | @Override 22 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_176500_f" : "checkWitherSpawn"); } 23 | 24 | @Override 25 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 26 | /* 27 | * checkWitherSpawn: (changes are around line 245) 28 | * Old code: 29 | * worldIn.setBlockState(blockworldstate1.getPos(), Blocks.AIR.getDefaultState(), 2); 30 | * 31 | * New code: 32 | * worldIn.setBlockState(blockworldstate1.getPos(), FluidState.get(worldIn, pos).getState(), 2); 33 | */ 34 | if(checkField(insn, obfuscated ? "field_150350_a" : "AIR", "Lnet/minecraft/block/Block;")) { 35 | final InsnList list = new InsnList(); 36 | //parameters 37 | list.add(new VarInsnNode(ALOAD, 1)); 38 | list.add(new VarInsnNode(ALOAD, 2)); 39 | //adds new code 40 | list.add(genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidState", "get", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lgit/jbredwards/fluidlogged_api/api/util/FluidState;")); 41 | list.add(new MethodInsnNode(INVOKEVIRTUAL, "git/jbredwards/fluidlogged_api/api/util/FluidState", "getState", "()Lnet/minecraft/block/state/IBlockState;", false)); 42 | instructions.insertBefore(insn, list); 43 | removeFrom(instructions, insn, 1); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockStairs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 10 | import net.minecraft.block.Block; 11 | import net.minecraft.block.BlockStairs; 12 | import net.minecraft.util.EnumFacing; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.world.World; 15 | import org.objectweb.asm.tree.*; 16 | 17 | import javax.annotation.Nonnull; 18 | 19 | /** 20 | * update neighboring fluids when this changes shape 21 | * @author jbred 22 | * 23 | */ 24 | public final class PluginBlockStairs implements IASMPlugin 25 | { 26 | @Override 27 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 28 | /* 29 | * New code: 30 | * // update neighboring fluids when this changes shape 31 | * @ASMGenerated 32 | * public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) 33 | * { 34 | * Hooks.notifyNeighboringFluids(worldIn, pos, blockIn, fromPos); 35 | * } 36 | */ 37 | addMethod(classNode, obfuscated ? "func_189540_a" : "neighborChanged", "(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/Block;Lnet/minecraft/util/math/BlockPos;)V", 38 | "notifyNeighboringFluids", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/Block;Lnet/minecraft/util/math/BlockPos;)V", generator -> { 39 | generator.visitVarInsn(ALOAD, 2); 40 | generator.visitVarInsn(ALOAD, 3); 41 | generator.visitVarInsn(ALOAD, 4); 42 | generator.visitVarInsn(ALOAD, 5); 43 | } 44 | ); 45 | 46 | return false; 47 | } 48 | 49 | @SuppressWarnings("unused") 50 | public static final class Hooks 51 | { 52 | public static void notifyNeighboringFluids(@Nonnull final World world, @Nonnull final BlockPos pos, @Nonnull final Block blockIn, @Nonnull final BlockPos fromPos) { 53 | if(pos.getY() == fromPos.getY() && (BlockStairs.isBlockStairs(blockIn.getDefaultState()) || BlockStairs.isBlockStairs(world.getBlockState(fromPos)))) FluidloggedUtils.notifyFluids(world, pos, null, false, EnumFacing.UP, EnumFacing.DOWN); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockStateContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.ClassNode; 10 | import org.objectweb.asm.tree.FieldNode; 11 | 12 | import javax.annotation.Nonnull; 13 | 14 | /** 15 | * store a level-to-FluidState lookup array in fluid block state containers 16 | * @author jbred 17 | * 18 | */ 19 | public final class PluginBlockStateContainer implements IASMPlugin 20 | { 21 | @Override 22 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 23 | classNode.fields.add(new FieldNode(ACC_PUBLIC, "fluidStates", "[[Lgit/jbredwards/fluidlogged_api/api/util/FluidState;", null, null)); 24 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/mod/asm/iface/ILevelFluidStateLookup"); 25 | /* 26 | * Accessor: 27 | * New code: 28 | * // getter for fluidStates 29 | * @ASMGenerated 30 | * public FluidState[][] getFluidStateLookup() 31 | * { 32 | * return this.fluidStates; 33 | * } 34 | */ 35 | addMethod(classNode, "getFluidStateLookup", "()[[Lgit/jbredwards/fluidlogged_api/api/util/FluidState;", null, null, generator -> { 36 | generator.visitVarInsn(ALOAD, 0); 37 | generator.visitFieldInsn(GETFIELD, "net/minecraft/block/state/BlockStateContainer", "fluidStates", "[[Lgit/jbredwards/fluidlogged_api/api/util/FluidState;"); 38 | }); 39 | /* 40 | * Accessor: 41 | * New code: 42 | * // setter for fluidStates 43 | * @ASMGenerated 44 | * public void setFluidStateLookup(@Nonnull FluidState[][] fluidStates) 45 | * { 46 | * this.fluidStates = fluidStates; 47 | * } 48 | */ 49 | addMethod(classNode, "setFluidStateLookup", "([[Lgit/jbredwards/fluidlogged_api/api/util/FluidState;)V", null, null, generator -> { 50 | generator.visitVarInsn(ALOAD, 0); 51 | generator.visitVarInsn(ALOAD, 1); 52 | generator.visitFieldInsn(PUTFIELD, "net/minecraft/block/state/BlockStateContainer", "fluidStates", "[[Lgit/jbredwards/fluidlogged_api/api/util/FluidState;"); 53 | }); 54 | 55 | return false; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockTrapDoor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.AbstractInsnNode; 10 | import org.objectweb.asm.tree.InsnList; 11 | import org.objectweb.asm.tree.InsnNode; 12 | import org.objectweb.asm.tree.MethodNode; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * trapdoors now notify neighbors when opening/closing 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginBlockTrapDoor implements IASMPlugin 22 | { 23 | @Override 24 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(obfuscated ? "func_180639_a" : "onBlockActivated") || method.name.equals(obfuscated ? "func_189540_a" : "neighborChanged"); } 25 | 26 | @Override 27 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 28 | /* 29 | * onBlockActivated & neighborChanged: (changes are around lines 122 & 159) 30 | * Old code: 31 | * worldIn.setBlockState(pos, state, 2); 32 | * ... 33 | * worldIn.setBlockState(pos, state.withProperty(OPEN, Boolean.valueOf(flag)), 2); 34 | * 35 | * New code: 36 | * // notify neighbors of state change 37 | * worldIn.setBlockState(pos, state, 3); 38 | * ... 39 | * worldIn.setBlockState(pos, state.withProperty(OPEN, Boolean.valueOf(flag)), 3); 40 | */ 41 | if(insn.getOpcode() == ICONST_2 && checkMethod(insn.getNext(), obfuscated ? "func_180501_a" : "setBlockState")) { 42 | instructions.insertBefore(insn, new InsnNode(ICONST_3)); 43 | instructions.remove(insn); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/block/PluginBlockWall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.IBlockAccess; 13 | import org.objectweb.asm.tree.*; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * Fix wall fluid interaction 19 | * @author jbred 20 | * 21 | */ 22 | public final class PluginBlockWall implements IASMPlugin 23 | { 24 | @Override 25 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_176221_a" : "getActualState"); } 26 | 27 | @Override 28 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 29 | /* 30 | * getActualState (changes are around line 209): 31 | * Old code: 32 | * return state.withProperty(UP, Boolean.valueOf(!flag4 || !worldIn.isAirBlock(pos.up()))).withProperty(NORTH, Boolean.valueOf(flag)).withProperty(EAST, Boolean.valueOf(flag1)).withProperty(SOUTH, Boolean.valueOf(flag2)).withProperty(WEST, Boolean.valueOf(flag3)); 33 | * 34 | * New code: 35 | * //don't have up post if the block above is a fluid 36 | * return state.withProperty(UP, Boolean.valueOf(!flag4 || !Hooks.isAirOrFluid(worldIn, pos.up()))).withProperty(NORTH, Boolean.valueOf(flag)).withProperty(EAST, Boolean.valueOf(flag1)).withProperty(SOUTH, Boolean.valueOf(flag2)).withProperty(WEST, Boolean.valueOf(flag3)); 37 | */ 38 | if(checkMethod(insn, obfuscated ? "func_175623_d" : "isAirBlock", "(Lnet/minecraft/util/math/BlockPos;)Z")) { 39 | instructions.insert(insn, genMethodNode("isAirOrFluid", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Z")); 40 | instructions.remove(insn); 41 | return true; 42 | } 43 | 44 | return false; 45 | } 46 | 47 | @SuppressWarnings("unused") 48 | public static final class Hooks 49 | { 50 | public static boolean isAirOrFluid(@Nonnull IBlockAccess world, @Nonnull BlockPos pos) { 51 | final IBlockState here = world.getBlockState(pos); 52 | return here.getBlock().isAir(here, world, pos) || FluidloggedUtils.isFluid(here); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/client/PluginActiveRenderInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.client; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * get block fog color from possible FluidState 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginActiveRenderInfo implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_186703_a" : "getBlockStateAtEntityViewpoint"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * getBlockStateAtEntityViewpoint: (changes are around line 82) 27 | * Old code: 28 | * IBlockState iblockstate = worldIn.getBlockState(blockpos); 29 | * 30 | * New code: 31 | * //use FluidState fog color rather than state here 32 | * IBlockState iblockstate = FluidloggedUtils.getFluidOrReal(worldIn, blockpos); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 36 | instructions.remove(insn); 37 | return false; 38 | } 39 | /* 40 | * getBlockStateAtEntityViewpoint: (changes are around line 84) 41 | * Old code: 42 | * if (iblockstate.getMaterial().isLiquid()) 43 | * { 44 | * ... 45 | * } 46 | * 47 | * New code: 48 | * //skip built-in BlockLiquid special case, it's been moved to BlockLiquid directly 49 | * if (false) 50 | * { 51 | * ... 52 | * } 53 | */ 54 | else if(checkMethod(insn, obfuscated ? "func_76224_d" : "isLiquid")) { 55 | instructions.insert(new InsnNode(ICONST_0)); 56 | removeFrom(instructions, insn, -2); 57 | return true; 58 | } 59 | 60 | return false; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/client/PluginEntityPlayerSP.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.client; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.FluidloggedAPI; 10 | import net.minecraft.entity.player.EntityPlayer; 11 | import org.objectweb.asm.tree.*; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * disable sprint while in water 17 | * @author jbred 18 | * 19 | */ 20 | public final class PluginEntityPlayerSP implements IASMPlugin 21 | { 22 | @Override 23 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(obfuscated ? "func_70636_d" : "onLivingUpdate"); } 24 | 25 | @Override 26 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 27 | /* 28 | * onLivingUpdate: (changes are around line 1040) 29 | * Old code: 30 | * if (this.capabilities.allowFlying) 31 | * { 32 | * ... 33 | * } 34 | * 35 | * New code: 36 | * // disable sprint while in water 37 | * if (Hooks.canFlyDisableSprint(this.capabilities.allowFlying, this)) 38 | * { 39 | * ... 40 | * } 41 | */ 42 | if(checkField(insn, obfuscated ? "field_75101_c" : "allowFlying") && !(getPrevious(insn, 3) instanceof JumpInsnNode)) { 43 | instructions.insert(insn, genMethodNode("canFlyDisableSprint", "(ZLnet/minecraft/entity/player/EntityPlayer;)Z")); 44 | instructions.insert(insn, new VarInsnNode(ALOAD, 0)); 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | 51 | @SuppressWarnings("unused") 52 | public static final class Hooks 53 | { 54 | public static boolean canFlyDisableSprint(final boolean allowFlying, @Nonnull final EntityPlayer player) { 55 | if(!FluidloggedAPI.isAquaAcrobatics && !player.capabilities.isFlying && player.isInWater()) player.setSprinting(false); 56 | return allowFlying; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/client/PluginParticleRain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.client; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fix all fluid-related rain collisions 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginParticleRain implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_189213_a" : "onUpdate"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * onUpdate: (changes are around line 65) 27 | * Old code: 28 | * if (iblockstate.getBlock() instanceof BlockLiquid) 29 | * { 30 | * ... 31 | * } 32 | * 33 | * New code: 34 | * //disable built-in liquid check 35 | * if (false) 36 | * { 37 | * ... 38 | * } 39 | */ 40 | if(insn.getOpcode() == INSTANCEOF) { 41 | instructions.insert(insn, new InsnNode(ICONST_0)); 42 | removeFrom(instructions, insn, -2); 43 | } 44 | /* 45 | * onUpdate: (changes are around line 71) 46 | * Old code: 47 | * d0 = iblockstate.getBoundingBox(this.world, blockpos).maxY; 48 | * 49 | * New code: 50 | * //rain particles collide at the proper height 51 | * d0 = PluginEntityRenderer.Hooks(iblockstate, this.world, blockpos).maxY; 52 | */ 53 | else if(checkMethod(insn, obfuscated ? "func_185900_c" : "getBoundingBox")) { 54 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/client/PluginEntityRenderer$Hooks", "fixRainCollision", "(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/math/AxisAlignedBB;")); 55 | instructions.remove(insn); 56 | return true; 57 | } 58 | 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/client/PluginWaterParticles.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.client; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * these particles don't instantly disappear while inside water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginWaterParticles implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_189213_a" : "onUpdate"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * onUpdate: (changes are around line 38) 27 | * Old code: 28 | * if (this.world.getBlockState(new BlockPos(this.posX, this.posY, this.posZ)).getMaterial() != Material.WATER) 29 | * { 30 | * ... 31 | * } 32 | * 33 | * New code: 34 | * //this particle doesn't disappear while within a water FluidState 35 | * if (FluidloggedUtils.getFluidOrReal(this.world, new BlockPos(this.posX, this.posY, this.posZ)).getMaterial() != Material.WATER) 36 | * { 37 | * ... 38 | * } 39 | */ 40 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState", null)) { 41 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 42 | instructions.remove(insn); 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/entity/PluginEntityAIPanic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.entity; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * water FluidStates are now seen as water blocks 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginEntityAIPanic implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_188497_a" : "getRandPos"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * getRandPos: (changes are around line 106): 27 | * Old code: 28 | * IBlockState iblockstate = worldIn.getBlockState(blockpos$mutableblockpos); 29 | * 30 | * New code: 31 | * //account for FluidStates 32 | * IBlockState iblockstate = FluidloggedUtils.getFluidOrReal(worldIn, blockpos$mutableblockpos); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 36 | instructions.remove(insn); 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/entity/PluginEntityBoat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.entity; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * boats work with water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginEntityBoat implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { 22 | return checkMethod(method, obfuscated ? "func_184451_k" : "getWaterLevelAbove", "()F") 23 | || checkMethod(method, obfuscated ? "func_184446_u" : "checkInWater", "()Z") 24 | || checkMethod(method, obfuscated ? "func_184444_v" : "getUnderwaterStatus", "()Lnet/minecraft/entity/item/EntityBoat$Status;") 25 | || checkMethod(method, obfuscated ? "func_184231_a" : "updateFallState", "(DZLnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/math/BlockPos;)V"); 26 | } 27 | 28 | @Override 29 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 30 | /* 31 | * getWaterLevelAbove, checkInWater, getUnderwaterStatus, updateFallState: (changes are around lines 502, 613, 668, and 945) 32 | * Old code: 33 | * IBlockState iblockstate = this.world.getBlockState(blockpos$pooledmutableblockpos); 34 | * 35 | * New code: 36 | * //account for FluidStates 37 | * IBlockState iblockstate = FluidloggedUtils.getFluidOrReal(this.world, blockpos$pooledmutableblockpos); 38 | */ 39 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 40 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 41 | instructions.remove(insn); 42 | return true; 43 | } 44 | 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/entity/PluginEntityFishHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.entity; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * fishhook entities generate the fishing particles at water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginEntityFishHook implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { 22 | return method.name.equals(obfuscated ? "func_70071_h_" : "onUpdate") 23 | || method.name.equals(obfuscated ? "func_190621_a" : "catchingFish"); 24 | } 25 | 26 | @Override 27 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 28 | /* 29 | * onUpdate & cachingFish: (changes are around lines 174, 428, and 478) 30 | * Old code: 31 | * IBlockState iblockstate = this.world.getBlockState(blockpos); 32 | * 33 | * New code: 34 | * //account for FluidStates 35 | * IBlockState iblockstate = FluidloggedUtils.getFluidOrReal(this.world, blockpos); 36 | */ 37 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 38 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 39 | instructions.remove(insn); 40 | } 41 | 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/entity/PluginEntityItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.entity; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * handle lava collisions correctly 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginEntityItem implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_70071_h_" : "onUpdate"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * onUpdate: (changes are around line 137) 27 | * Old code: 28 | * if (this.world.getBlockState(new BlockPos(this)).getMaterial() == Material.LAVA) 29 | * { 30 | * ... 31 | * } 32 | * 33 | * New code: 34 | * //use better lava check that accounts for FluidStates 35 | * if (this.world.isMaterialInBB(this.getEntityBoundingBox(), Material.LAVA)) 36 | * { 37 | * ... 38 | * } 39 | */ 40 | if(checkField(insn, obfuscated ? "field_151587_i" : "LAVA")) { 41 | ((JumpInsnNode)insn.getNext()).setOpcode(IFEQ); 42 | removeFrom(instructions, insn.getPrevious(), -2); 43 | removeFrom(instructions, getPrevious(insn, 2), -1); 44 | instructions.insertBefore(insn, new MethodInsnNode(INVOKESPECIAL, "net/minecraft/entity/Entity", obfuscated ? "func_174813_aQ" : "getEntityBoundingBox", "()Lnet/minecraft/util/math/AxisAlignedBB;", false)); 45 | instructions.insert(insn, new MethodInsnNode(INVOKEVIRTUAL, "net/minecraft/world/World", obfuscated ? "func_72875_a" : "isMaterialInBB", "(Lnet/minecraft/util/math/AxisAlignedBB;Lnet/minecraft/block/material/Material;)Z", false)); 46 | return true; 47 | } 48 | 49 | return false; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/entity/PluginEntityMinecart.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.entity; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import net.minecraft.entity.Entity; 10 | import org.objectweb.asm.tree.AbstractInsnNode; 11 | import org.objectweb.asm.tree.InsnList; 12 | import org.objectweb.asm.tree.MethodNode; 13 | import org.objectweb.asm.tree.VarInsnNode; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * minecarts account for fluids when applying drag 19 | * @author jbred 20 | * 21 | */ 22 | public final class PluginEntityMinecart implements IASMPlugin 23 | { 24 | @Override 25 | public boolean isMethodValid(@Nonnull final MethodNode method, final boolean obfuscated) { return method.name.equals(obfuscated ? "func_94101_h" : "applyDrag"); } 26 | 27 | @Override 28 | public boolean transform(@Nonnull final InsnList instructions, @Nonnull final MethodNode method, @Nonnull final AbstractInsnNode insn, final boolean obfuscated, final int index) { 29 | /* 30 | * applyDrag: (changes are around line 731) 31 | * Old code: 32 | * { 33 | * ... 34 | * } 35 | * 36 | * New code: 37 | * // append fluid drag logic to the end of the method 38 | * { 39 | * ... 40 | * Hooks.applyFluidDrag(this); 41 | * } 42 | */ 43 | if(insn.getOpcode() == RETURN) { 44 | instructions.insertBefore(insn, new VarInsnNode(ALOAD, 0)); 45 | instructions.insertBefore(insn, genMethodNode("applyFluidDrag", "(Lnet/minecraft/entity/Entity;)V")); 46 | return true; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | @SuppressWarnings("unused") 53 | public static final class Hooks 54 | { 55 | public static void applyFluidDrag(@Nonnull final Entity minecart) { 56 | if(minecart.isInWater() && minecart.isPushedByWater()) { 57 | minecart.motionX *= 0.8; 58 | minecart.motionZ *= 0.8; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/entity/PluginRandomPositionGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.entity; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * water FluidStates are now seen as water blocks 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginRandomPositionGenerator implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_191380_b" : "isWaterDestination"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * isWaterDestination: (changes are around line 179) 27 | * Old code: 28 | * return p_191380_1_.world.getBlockState(p_191380_0_).getMaterial() == Material.WATER; 29 | * 30 | * New code: 31 | * //account for FluidStates 32 | * return FluidloggedUtils.getFluidOrReal(p_191380_1_.world, p_191380_0_).getMaterial() == Material.WATER; 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 35 | instructions.insert(insn, genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidOrReal", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 36 | instructions.remove(insn); 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/item/PluginItemArmorStand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.item; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 10 | import net.minecraft.util.math.BlockPos; 11 | import net.minecraft.world.World; 12 | import org.objectweb.asm.tree.*; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * armor stands don't remove fluids at their position when placed 18 | * @author jbred 19 | * 20 | */ 21 | public final class PluginItemArmorStand implements IASMPlugin 22 | { 23 | @Override 24 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_180614_a" : "onItemUse"); } 25 | 26 | @Override 27 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 28 | /* 29 | * onItemUse: (changes are around lines 71-72) 30 | * Old code: 31 | * worldIn.setBlockToAir(blockpos); 32 | * worldIn.setBlockToAir(blockpos1); 33 | * 34 | * New code: 35 | * armor stands don't remove fluids at their position when placed 36 | * Hooks.setBlockToAirIfNonFluid(worldIn, blockpos); 37 | * Hooks.setBlockToAirIfNonFluid(worldIn, blockpos1); 38 | */ 39 | if(checkMethod(insn.getPrevious(), obfuscated ? "func_175698_g" : "setBlockToAir")) { 40 | final boolean isDone = getNext(insn, 3).getOpcode() == NEW; 41 | instructions.insert(insn, genMethodNode("setBlockToAirIfNonFluid", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)V")); 42 | removeFrom(instructions, insn, -1); 43 | return isDone; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | @SuppressWarnings("unused") 50 | public static final class Hooks 51 | { 52 | public static void setBlockToAirIfNonFluid(@Nonnull World world, @Nonnull BlockPos pos) { 53 | if(!FluidloggedUtils.isFluid(world.getBlockState(pos))) world.setBlockToAir(pos); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/item/PluginItemGlassBottle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.item; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * glass bottles can now be filled by using water FluidStates 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginItemGlassBottle implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_77659_a" : "onItemRightClick"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * onItemRightClick: (changes are around line 71) 27 | * Old code: 28 | * if (worldIn.getBlockState(blockpos).getMaterial() == Material.WATER) 29 | * { 30 | * ... 31 | * } 32 | * 33 | * New code: 34 | * //check for specifically water and account for FluidStates 35 | * if (FluidloggedUtils.isCompatibleFluid(FluidloggedUtils.getFluidState(worldIn, blockpos).getFluid(), FluidRegistry.WATER)) 36 | * { 37 | * ... 38 | * } 39 | */ 40 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 41 | ((JumpInsnNode)getNext(insn, 3)).setOpcode(IFEQ); 42 | final InsnList list = new InsnList(); 43 | list.add(genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "getFluidState", "(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lgit/jbredwards/fluidlogged_api/api/util/FluidState;")); 44 | list.add(new MethodInsnNode(INVOKEVIRTUAL, "git/jbredwards/fluidlogged_api/api/util/FluidState", "getFluid", "()Lnet/minecraftforge/fluids/Fluid;", false)); 45 | list.add(new FieldInsnNode(GETSTATIC, "net/minecraftforge/fluids/FluidRegistry", "WATER", "Lnet/minecraftforge/fluids/Fluid;")); 46 | list.add(genMethodNode("git/jbredwards/fluidlogged_api/api/util/FluidloggedUtils", "isCompatibleFluid", "(Lnet/minecraftforge/fluids/Fluid;Lnet/minecraftforge/fluids/Fluid;)Z")); 47 | 48 | instructions.insertBefore(insn, list); 49 | removeFrom(instructions, insn, 2); 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/item/PluginItemLilyPad.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.item; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block.PluginBlockLilyPad; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.World; 13 | import org.objectweb.asm.tree.*; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * lily pads can be placed on certain water FluidStates 19 | * @author jbred 20 | * 21 | */ 22 | public final class PluginItemLilyPad implements IASMPlugin 23 | { 24 | @Override 25 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_77659_a" : "onItemRightClick"); } 26 | 27 | @Override 28 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 29 | /* 30 | * onItemRightClick: (changes are around line 52) 31 | * Old code: 32 | * IBlockState iblockstate = worldIn.getBlockState(pos.down()); 33 | * 34 | * New code: 35 | * //use the FluidState if the state below is less than 1 block tall 36 | * IBlockState iblockstate = Hooks.getFluidIfApplicable(worldIn, pos.down()); 37 | */ 38 | if(checkMethod(insn, obfuscated ? "func_180495_p" : "getBlockState")) { 39 | instructions.insert(insn, genMethodNode("getFluidIfApplicable", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;")); 40 | instructions.remove(insn); 41 | return true; 42 | } 43 | 44 | return false; 45 | } 46 | 47 | @SuppressWarnings("unused") 48 | public static final class Hooks 49 | { 50 | @Nonnull 51 | public static IBlockState getFluidIfApplicable(@Nonnull World world, @Nonnull BlockPos pos) { 52 | return PluginBlockLilyPad.Hooks.getFluidIfApplicable(world, pos); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/world/PluginChunkPrimer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.world; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * allow mods to generate FluidStates more optimally during world gen 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginChunkPrimer implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(""); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | //call super on correct class 26 | if(checkMethod(insn, "")) { 27 | ((MethodInsnNode)insn).owner = "git/jbredwards/fluidlogged_api/api/world/IFluidStatePrimer"; 28 | return true; 29 | } 30 | 31 | return false; 32 | } 33 | 34 | @Override 35 | public boolean transformClass(@Nonnull ClassNode classNode, boolean obfuscated) { 36 | classNode.superName = "git/jbredwards/fluidlogged_api/api/world/IFluidStatePrimer"; 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/plugins/vanilla/world/PluginDragonSpawnManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.world; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * summoning the ender dragon will now void FluidStates at the pillar locations 15 | * @author jbred 16 | * 17 | */ 18 | public final class PluginDragonSpawnManager implements IASMPlugin 19 | { 20 | @Override 21 | public boolean isMethodValid(@Nonnull MethodNode method, boolean obfuscated) { return method.name.equals(obfuscated ? "func_186079_a" : "process"); } 22 | 23 | @Override 24 | public boolean transform(@Nonnull InsnList instructions, @Nonnull MethodNode method, @Nonnull AbstractInsnNode insn, boolean obfuscated, int index) { 25 | /* 26 | * process: (changes are around line 72) 27 | * Old code: 28 | * worldIn.setBlockToAir(blockpos$mutableblockpos); 29 | * 30 | * New code: 31 | * void FluidStates at the pillar locations 32 | * worldIn.setBlockState(blockpos$mutableblockpos, Blocks.AIR.getDefaultState()); 33 | */ 34 | if(checkMethod(insn, obfuscated ? "func_175698_g" : "setBlockToAir")) { 35 | final InsnList list = new InsnList(); 36 | list.add(new FieldInsnNode(GETSTATIC, "net/minecraft/init/Blocks", obfuscated ? "field_150350_a" : "AIR", "Lnet/minecraft/block/Block;")); 37 | list.add(new MethodInsnNode(INVOKEVIRTUAL, "net/minecraft/block/Block", obfuscated ? "func_176223_P" : "getDefaultState", "()Lnet/minecraft/block/state/IBlockState;", false)); 38 | list.add(new MethodInsnNode(INVOKEVIRTUAL, "net/minecraft/world/World", obfuscated ? "func_175656_a" : "setBlockState", "(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z", false)); 39 | instructions.insert(insn, list); 40 | instructions.remove(insn); 41 | return true; 42 | } 43 | 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/transformers/TransformerModdedWalls.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.transformers; 7 | 8 | import git.jbredwards.fluidlogged_api.api.asm.IASMPlugin; 9 | import git.jbredwards.fluidlogged_api.mod.asm.plugins.vanilla.block.PluginBlockWall; 10 | import net.minecraft.launchwrapper.IClassTransformer; 11 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 12 | import org.objectweb.asm.tree.ClassNode; 13 | 14 | import javax.annotation.Nonnull; 15 | import javax.annotation.Nullable; 16 | 17 | /** 18 | * Many modded wall blocks don't extend BlockWall and instead copy all the code from BlockWall. 19 | * This transformer attempts to find all modded wall block classes, and applies the {@link PluginBlockWall} fix 20 | * & the {@link git.jbredwards.fluidlogged_api.mod.asm.iface.IModdedWall} interface (so they can be easily 21 | * identified as walls, used by this mod's builtin whitelist). 22 | * @author jbred 23 | * 24 | */ 25 | public final class TransformerModdedWalls implements IClassTransformer, IASMPlugin 26 | { 27 | @Nullable 28 | @Override 29 | public byte[] transform(@Nullable final String name, @Nullable final String transformedName, @Nullable final byte[] basicClass) { 30 | return basicClass != null && transformedName != null && transformedName.contains("Wall") ? transform(basicClass, !FMLLaunchHandler.isDeobfuscatedEnvironment()) : basicClass; 31 | } 32 | 33 | @Override 34 | public boolean transformClass(@Nonnull final ClassNode classNode, final boolean obfuscated) { 35 | if(classNode.methods.stream().anyMatch(method -> checkMethod(method, "getAABBIndex", "(Lnet/minecraft/block/state/IBlockState;)I"))) { 36 | IASMPlugin.setActivePlugin("Fluidlogged API Plugin"); 37 | classNode.interfaces.add("git/jbredwards/fluidlogged_api/mod/asm/iface/IModdedWall"); 38 | new PluginBlockWall().transformNode(classNode, obfuscated); 39 | IASMPlugin.resetActivePlugin(); 40 | } 41 | 42 | return false; 43 | } 44 | 45 | @Override 46 | public boolean shouldInformConsole() { return false; /* handled by PluginBlockWall */ } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/asm/transformers/TransformerSmoothWater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.asm.transformers; 7 | 8 | import net.minecraft.launchwrapper.IClassTransformer; 9 | import org.objectweb.asm.*; 10 | 11 | import javax.annotation.Nonnull; 12 | import javax.annotation.Nullable; 13 | 14 | /** 15 | * revert super class changes made by SmoothWater 16 | * @author jbred 17 | * 18 | */ 19 | @SuppressWarnings("unused") 20 | public final class TransformerSmoothWater implements IClassTransformer 21 | { 22 | @Nullable 23 | @Override 24 | public byte[] transform(@Nonnull String name, @Nonnull String transformedName, @Nullable byte[] basicClass) { 25 | if(basicClass == null) return null; 26 | final ClassReader reader = new ClassReader(basicClass); 27 | if(isSmoothWaterClass(reader.getSuperName())) { 28 | final ClassWriter writer = new ClassWriter(0); 29 | reader.accept(new ClassVisitor(Opcodes.ASM5, writer) { 30 | @Override 31 | public void visit(int version, int access, @Nonnull String name, @Nonnull String signature, @Nonnull String superName, @Nonnull String[] interfaces) { 32 | super.visit(version, access, name, signature, "net/minecraft/block/BlockLiquid", interfaces); 33 | } 34 | 35 | @Nonnull 36 | @Override 37 | public MethodVisitor visitMethod(int access, @Nonnull String name, @Nonnull String desc, @Nonnull String signature, @Nonnull String[] exceptions) { 38 | final MethodVisitor old = super.visitMethod(access, name, desc, signature, exceptions); 39 | return "".equals(name) ? new MethodVisitor(Opcodes.ASM5, old) { 40 | @Override 41 | public void visitMethodInsn(int opcode, @Nonnull String owner, @Nonnull String name, @Nonnull String desc, boolean itf) { 42 | super.visitMethodInsn(opcode, isSmoothWaterClass(owner) ? "net/minecraft/block/BlockLiquid" : owner, name, desc, itf); 43 | } 44 | } : old; 45 | } 46 | }, 0); 47 | 48 | return writer.toByteArray(); 49 | } 50 | 51 | return basicClass; 52 | } 53 | 54 | static boolean isSmoothWaterClass(@Nonnull String clazz) { 55 | return "pl/asie/smoothwater/BlockLiquidForged".equals(clazz) || "pl/asie/mage/core/water/BlockLiquidForged".equals(clazz); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/client/gui/FluidloggedAPIGuiFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.client.gui; 7 | 8 | import git.jbredwards.fluidlogged_api.mod.FluidloggedAPI; 9 | import git.jbredwards.fluidlogged_api.mod.common.config.FluidloggedAPIConfig; 10 | import net.minecraft.client.Minecraft; 11 | import net.minecraft.client.gui.GuiScreen; 12 | import net.minecraft.client.resources.I18n; 13 | import net.minecraftforge.common.config.ConfigElement; 14 | import net.minecraftforge.fml.client.IModGuiFactory; 15 | import net.minecraftforge.fml.client.config.DummyConfigElement; 16 | import net.minecraftforge.fml.client.config.IConfigElement; 17 | import net.minecraftforge.fml.relauncher.Side; 18 | import net.minecraftforge.fml.relauncher.SideOnly; 19 | 20 | import javax.annotation.Nonnull; 21 | import javax.annotation.Nullable; 22 | import java.util.ArrayList; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import java.util.Set; 26 | 27 | /** 28 | * 29 | * @author jbred 30 | * 31 | */ 32 | @SideOnly(Side.CLIENT) 33 | public final class FluidloggedAPIGuiFactory implements IModGuiFactory 34 | { 35 | @Override 36 | public void initialize(@Nonnull final Minecraft minecraftInstance) {} 37 | 38 | @Override 39 | public boolean hasConfigGui() { return true; } 40 | 41 | @Nonnull 42 | @Override 43 | public GuiScreen createConfigGui(@Nonnull final GuiScreen parentScreen) { 44 | @Nonnull final List configElements = new ArrayList<>(); 45 | configElements.add(ConfigElement.from(FluidloggedAPIConfig.class)); 46 | // special category handlers 47 | configElements.add(new DummyConfigElement.DummyCategoryElement("fluidlogged_api/fluidTags", "configgui.fluidlogged_api.fluidTags", Collections.emptyList())); 48 | configElements.add(new DummyConfigElement.DummyCategoryElement("fluidlogged_api/blacklist", "configgui.fluidlogged_api.blacklist", Collections.emptyList())); 49 | configElements.add(new DummyConfigElement.DummyCategoryElement("fluidlogged_api/whitelist", "configgui.fluidlogged_api.whitelist", Collections.emptyList())); 50 | // don't change main gui screen 51 | return new GuiComponentConfig(parentScreen, configElements, FluidloggedAPI.MODID, false, false, I18n.format("configgui.fluidlogged_api.configTitle")); 52 | } 53 | 54 | // NO-OP 55 | @Nullable 56 | @Override 57 | public Set runtimeGuiCategories() { return null; } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/client/gui/GuiComponentConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.client.gui; 7 | 8 | import net.minecraft.client.gui.GuiScreen; 9 | import net.minecraftforge.fml.client.config.GuiConfig; 10 | import net.minecraftforge.fml.client.config.GuiConfigEntries; 11 | import net.minecraftforge.fml.client.config.IConfigElement; 12 | import net.minecraftforge.fml.relauncher.Side; 13 | import net.minecraftforge.fml.relauncher.SideOnly; 14 | 15 | import javax.annotation.Nonnull; 16 | import javax.annotation.Nullable; 17 | import java.util.List; 18 | 19 | /** 20 | * 21 | * @author jbred 22 | * 23 | */ 24 | @SideOnly(Side.CLIENT) 25 | public class GuiComponentConfig extends GuiConfig 26 | { 27 | public GuiComponentConfig(@Nonnull final GuiScreen parentScreen, @Nonnull final List configElements, @Nonnull final String modID, final boolean allRequireWorldRestart, final boolean allRequireMcRestart, @Nonnull final String title) { 28 | this(parentScreen, configElements, modID, allRequireWorldRestart, allRequireMcRestart, title, null); 29 | } 30 | 31 | public GuiComponentConfig(@Nonnull final GuiScreen parentScreen, @Nonnull final List configElements, @Nonnull final String modID, final boolean allRequireWorldRestart, final boolean allRequireMcRestart, @Nonnull final String title, @Nullable final String titleLine2) { 32 | super(parentScreen, configElements, modID, allRequireWorldRestart, allRequireMcRestart, title, titleLine2); 33 | } 34 | 35 | @Override 36 | public void initGui() { 37 | final boolean loadComponentEntries = needsRefresh; 38 | super.initGui(); 39 | 40 | if(loadComponentEntries) entryList.listEntries.replaceAll(entry -> entry instanceof GuiConfigEntries.CategoryEntry ? new GuiConfigEntries.CategoryEntry(this, entryList, entry.getConfigElement()) { 41 | @Nonnull 42 | @Override 43 | protected GuiScreen buildChildScreen() { 44 | return new GuiComponentConfig(owningScreen, configElement.getChildElements(), owningScreen.modID, 45 | owningScreen.allRequireWorldRestart || configElement.requiresWorldRestart(), owningScreen.allRequireMcRestart || configElement.requiresMcRestart(), 46 | owningScreen.title, ((owningScreen.titleLine2 == null ? "" : owningScreen.titleLine2) + " > " + name)); 47 | } 48 | 49 | @Override 50 | public boolean enabled() { return !configElement.getChildElements().isEmpty(); } 51 | } : new ComponentConfigEntry(entry)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/client/optifine/OptifineHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.client.optifine; 7 | 8 | import git.jbredwards.fluidlogged_api.mod.asm.plugins.modded.optifine.PluginIResolvable; 9 | import net.minecraft.init.Biomes; 10 | import net.minecraft.util.math.BlockPos; 11 | import net.minecraft.world.biome.Biome; 12 | import net.minecraft.world.biome.BiomeColorHelper; 13 | import net.minecraftforge.fml.relauncher.ReflectionHelper; 14 | 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.InvocationTargetException; 17 | import java.lang.reflect.Method; 18 | 19 | /** 20 | * Support for Optifine's custom water colors 21 | * @author jbred 22 | * 23 | */ 24 | public final class OptifineHelper 25 | { 26 | static final Field waterColors_Field; 27 | static final Method getColor_Method; 28 | static final Method isSwampColors_Method; 29 | static { 30 | try { 31 | //noinspection deprecation 32 | waterColors_Field = ReflectionHelper.findField(Class.forName("net.optifine.CustomColors"), "waterColors"); 33 | //noinspection deprecation 34 | getColor_Method = ReflectionHelper.findMethod(Class.forName("net.optifine.CustomColormap"), "getColor", null, Biome.class, BlockPos.class); 35 | //noinspection deprecation 36 | isSwampColors_Method = ReflectionHelper.findMethod(Class.forName("Config"), "isSwampColors", null); 37 | } 38 | 39 | //should never be thrown 40 | catch(final ClassNotFoundException e) { throw new RuntimeException(e); } 41 | } 42 | 43 | public static void setWaterColorHelper() { 44 | BiomeColorHelper.WATER_COLOR = (biome, blockPos) -> { 45 | try { 46 | //OF has a setting to toggle swampland colors. If it's set to not support swamp colors, set to plains (this is what OF does) 47 | if(biome == Biomes.SWAMPLAND && !(boolean)isSwampColors_Method.invoke(null)) biome = Biomes.PLAINS; 48 | 49 | final Object waterColors = waterColors_Field.get(null); 50 | if(waterColors == null) return biome.getWaterColor(); //current resource pack has no water color change 51 | 52 | final int colorOF = (int)getColor_Method.invoke(waterColors, biome, blockPos); 53 | return colorOF != -1 ? colorOF : biome.getWaterColor(); 54 | } 55 | 56 | //should never be thrown 57 | catch(final IllegalAccessException | InvocationTargetException e) { throw new RuntimeException(e); } 58 | }; 59 | } 60 | 61 | public static void onLoadComplete() { PluginIResolvable.Hooks.resolve(); } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/capability/FluidStateCapabilityWrapped.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.capability; 7 | 8 | import git.jbredwards.fluidlogged_api.api.capability.IFluidStateCapability; 9 | import git.jbredwards.fluidlogged_api.api.capability.IFluidStateContainer; 10 | import git.jbredwards.fluidlogged_api.mod.asm.iface.IHardcodedCapability; 11 | import net.minecraft.nbt.NBTBase; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * Attached to Chunks to save/read existing data using forge's capability system. 17 | * @author jbred 18 | * 19 | */ 20 | public class FluidStateCapabilityWrapped implements IFluidStateCapability 21 | { 22 | @Nonnull 23 | protected final IHardcodedCapability wrapped; 24 | public FluidStateCapabilityWrapped(@Nonnull final IHardcodedCapability wrappedIn) { wrapped = wrappedIn; } 25 | 26 | @Nonnull 27 | @Override 28 | public IFluidStateContainer getContainer(final int y) { return wrapped.getFluidStateCapability().getContainer(y); } 29 | 30 | @Nonnull 31 | @Override 32 | public NBTBase serializeNBT() { return wrapped.getFluidStateCapability().serializeNBT(); } 33 | 34 | @Override 35 | public void deserializeNBT(@Nonnull final NBTBase nbt) { wrapped.getFluidStateCapability().deserializeNBT(nbt); } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/capability/cubicchunks/FluidStateCapabilityICube.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.capability.cubicchunks; 7 | 8 | import git.jbredwards.fluidlogged_api.mod.common.capability.FluidStateCapabilityVanilla; 9 | import io.github.opencubicchunks.cubicchunks.api.util.XYZAddressable; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | /** 14 | * Cubic Chunks mod compat, holds FluidStates within a 16x16x16 area 15 | * @author jbred 16 | * 17 | */ 18 | public class FluidStateCapabilityICube extends FluidStateCapabilityVanilla 19 | { 20 | protected final int offsetY; 21 | public FluidStateCapabilityICube(@Nonnull final XYZAddressable cube) { 22 | super(cube.getX(), cube.getZ()); 23 | offsetY = cube.getY() << 4; 24 | } 25 | 26 | @Override 27 | public int serializeY(final int y) { return (y & 15) << 8; } 28 | 29 | @Override 30 | public int deserializeY(final char serializedPos) { return offsetY | ((serializedPos >> 8) & 15); } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/capability/util/FluidStateLayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.capability.util; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | 10 | import javax.annotation.Nonnull; 11 | 12 | /** 13 | * Holds the data for FluidStates within a 16x1x16 area 14 | * @author jbred 15 | * 16 | */ 17 | public class FluidStateLayer 18 | { 19 | @Nonnull 20 | public FluidState[] data = new FluidState[256]; 21 | public byte tracker = Byte.MIN_VALUE; //start with min byte value, to prevent possible overflow problems 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/capability/util/FluidStateStorage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.capability.util; 7 | 8 | import git.jbredwards.fluidlogged_api.api.capability.IFluidStateCapability; 9 | import net.minecraft.nbt.NBTBase; 10 | import net.minecraft.util.EnumFacing; 11 | import net.minecraftforge.common.capabilities.Capability; 12 | 13 | import javax.annotation.Nonnull; 14 | import javax.annotation.Nullable; 15 | 16 | /** 17 | * 18 | * @author jbred 19 | * 20 | */ 21 | public enum FluidStateStorage implements Capability.IStorage 22 | { 23 | INSTANCE; 24 | 25 | @Nonnull 26 | @Override 27 | public NBTBase writeNBT(@Nullable final Capability capability, @Nonnull final IFluidStateCapability instance, @Nullable final EnumFacing side) { 28 | return instance.serializeNBT(); 29 | } 30 | 31 | @Override 32 | public void readNBT(@Nullable final Capability capability, @Nonnull final IFluidStateCapability instance, @Nullable final EnumFacing side, @Nonnull final NBTBase nbtIn) { 33 | instance.deserializeNBT(nbtIn); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/command/CommandChildBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.command; 7 | 8 | import net.minecraft.command.CommandBase; 9 | import net.minecraft.command.ICommand; 10 | import net.minecraft.command.ICommandSender; 11 | 12 | import javax.annotation.Nonnull; 13 | import javax.annotation.Nullable; 14 | 15 | /** 16 | * 17 | * @author jbred 18 | * 19 | */ 20 | public abstract class CommandChildBase extends CommandBase 21 | { 22 | @Nonnull 23 | protected final String name, usage; 24 | protected CommandChildBase(@Nullable final ICommand parentIn, @Nonnull final String nameIn) { 25 | name = nameIn; 26 | usage = "commands.fluidlogged_api." + (parentIn == null ? nameIn : (parentIn.getName() + "." + nameIn)) + ".usage"; 27 | } 28 | 29 | @Nonnull 30 | @Override 31 | public String getName() { return name; } 32 | 33 | @Nonnull 34 | @Override 35 | public String getUsage(@Nonnull final ICommandSender sender) { return usage; } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/command/CommandFluidloggedAPI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.command; 7 | 8 | import net.minecraft.command.ICommandSender; 9 | import net.minecraft.server.MinecraftServer; 10 | import net.minecraftforge.server.command.CommandTreeBase; 11 | import net.minecraftforge.server.command.CommandTreeHelp; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * 17 | * @author jbred 18 | * 19 | */ 20 | public final class CommandFluidloggedAPI extends CommandTreeBase 21 | { 22 | @Nonnull 23 | private final String name; 24 | public CommandFluidloggedAPI(@Nonnull final String nameIn) { 25 | name = nameIn; 26 | addSubcommand(new CommandPrint(this)); 27 | addSubcommand(new CommandReloadConfig(this, "reload")); 28 | addSubcommand(new CommandSetFluidState(this)); 29 | addSubcommand(new CommandTest(this)); 30 | addSubcommand(new CommandTreeHelp(this)); 31 | } 32 | 33 | @Override 34 | public int getRequiredPermissionLevel() { return 0; } 35 | 36 | @Nonnull 37 | @Override 38 | public String getName() { return name; } 39 | 40 | @Nonnull 41 | @Override 42 | public String getUsage(@Nonnull final ICommandSender sender) { return "commands.fluidlogged_api." + getName() + ".usage"; } 43 | 44 | @Override 45 | public boolean checkPermission(@Nonnull final MinecraftServer server, @Nonnull final ICommandSender sender) { return true; } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/command/CommandReloadConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.command; 7 | 8 | import git.jbredwards.fluidlogged_api.mod.common.config.FluidloggedAPIConfigs; 9 | import net.minecraft.command.*; 10 | import net.minecraft.server.MinecraftServer; 11 | 12 | import javax.annotation.Nonnull; 13 | import javax.annotation.Nullable; 14 | import java.io.IOException; 15 | 16 | /** 17 | * 18 | * @author jbred 19 | * 20 | */ 21 | public class CommandReloadConfig extends CommandChildBase 22 | { 23 | public CommandReloadConfig(@Nullable final ICommand parentIn, @Nonnull final String nameIn) { 24 | super(parentIn, nameIn); 25 | } 26 | 27 | @Override 28 | public void execute(@Nonnull final MinecraftServer server, @Nonnull final ICommandSender sender, @Nonnull final String[] args) throws CommandException { 29 | if(args.length != 0) throw new WrongUsageException(getUsage(sender)); 30 | else try { 31 | notifyCommandListener(sender, this, "commands.fluidlogged_api.reloadFluidloggedAPI.start"); 32 | FluidloggedAPIConfigs.initConfigs(server, true); 33 | notifyCommandListener(sender, this, "commands.fluidlogged_api.generic.finished"); 34 | } 35 | 36 | // oops 37 | catch(@Nonnull final IOException e) { 38 | e.printStackTrace(); 39 | throw new CommandException(e.getMessage()); 40 | } 41 | } 42 | 43 | @Nonnull 44 | @Override 45 | public String getName() { return name; } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/command/CommandTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.command; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import git.jbredwards.fluidlogged_api.api.util.FluidloggedUtils; 10 | import net.minecraft.block.Block; 11 | import net.minecraft.command.*; 12 | import net.minecraft.server.MinecraftServer; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.world.World; 15 | 16 | import javax.annotation.Nonnull; 17 | import javax.annotation.Nullable; 18 | import java.util.List; 19 | 20 | /** 21 | * 22 | * @author jbred 23 | * 24 | */ 25 | public class CommandTest extends CommandChildBase 26 | { 27 | public CommandTest(@Nullable final ICommand parentIn) { super(parentIn, "test"); } 28 | 29 | @Override 30 | public int getRequiredPermissionLevel() { return 1; } 31 | 32 | @Override 33 | public void execute(@Nonnull final MinecraftServer server, @Nonnull final ICommandSender sender, @Nonnull final String[] args) throws CommandException { 34 | if(args.length != 4 && args.length != 5) throw new WrongUsageException(getUsage(sender)); 35 | 36 | @Nonnull final BlockPos pos = parseBlockPos(sender, args, 0, false); 37 | @Nonnull final World world = sender.getEntityWorld(); 38 | if(!world.isBlockLoaded(pos)) throw new CommandException("commands.fluidlogged_api.test.outOfWorld"); 39 | 40 | @Nonnull final Block block = getBlockByText(sender, args[3]); 41 | @Nonnull final FluidState fluidState = args.length == 5 ? FluidState.of(convertArgToBlockState(block, args[4])) : FluidState.of(block); 42 | 43 | if(!fluidState.isValid()) throw new WrongUsageException(getUsage(sender)); 44 | else if(!FluidloggedUtils.isStateFluidloggable(world.getBlockState(pos), world, pos, fluidState)) throw new CommandException("commands.fluidlogged_api.test.fail"); 45 | else notifyCommandListener(sender, this, "commands.fluidlogged_api.test.success"); 46 | } 47 | 48 | @Nonnull 49 | @Override 50 | public List getTabCompletions(@Nonnull final MinecraftServer server, @Nonnull final ICommandSender sender, @Nonnull final String[] args, @Nullable final BlockPos targetPos) { 51 | if(args.length < 4) return args.length == 0 ? getListOfStringsMatchingLastWord(new String[0], getName()) : getTabCompletionCoordinate(args, 0, targetPos); 52 | @Nonnull final List matching = new CommandSetFluidState(null).getTabCompletions(server, sender, args, targetPos); 53 | 54 | matching.remove("minecraft:air"); 55 | return matching; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/config/handler/BlacklistConfigHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.config.handler; 7 | 8 | import com.google.gson.JsonObject; 9 | import git.jbredwards.fluidlogged_api.mod.FluidloggedAPI; 10 | import git.jbredwards.fluidlogged_api.mod.asm.iface.ICanFluidFlowHandler; 11 | import git.jbredwards.fluidlogged_api.mod.asm.iface.IConfigAccessor; 12 | import git.jbredwards.fluidlogged_api.mod.common.config.FluidloggedAPIConfigs; 13 | import git.jbredwards.fluidlogged_api.mod.common.config.util.ConfigPredicate; 14 | 15 | import javax.annotation.Nonnull; 16 | import java.io.IOException; 17 | 18 | /** 19 | * 20 | * @author jbred 21 | * 22 | */ 23 | public final class BlacklistConfigHandler 24 | { 25 | @Nonnull 26 | private static final String error = "An error occurred while parsing a blacklist entry in file \"%s\", skipping..."; 27 | public static void init(@Nonnull final JsonObject configs) throws IOException { 28 | // run for auto configs, mod instances, and user config 29 | FluidloggedAPIConfigs.forEach(configs, "BLACKLIST", "blacklist", (file, jsonIn) -> { 30 | try { ConfigPredicate.deserialize(file, jsonIn.getAsJsonObject(), IConfigAccessor::getBlacklistPredicate, IConfigAccessor::setBlacklistAndCache, ICanFluidFlowHandler::negate); } 31 | catch(@Nonnull final Throwable t) { FluidloggedAPI.LOGGER.error(String.format(error, file), t); } 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/config/handler/WhitelistConfigHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.config.handler; 7 | 8 | import com.google.gson.JsonObject; 9 | import git.jbredwards.fluidlogged_api.mod.FluidloggedAPI; 10 | import git.jbredwards.fluidlogged_api.mod.asm.iface.IConfigAccessor; 11 | import git.jbredwards.fluidlogged_api.mod.common.config.FluidloggedAPIConfigs; 12 | import git.jbredwards.fluidlogged_api.mod.common.config.util.ConfigPredicate; 13 | 14 | import javax.annotation.Nonnull; 15 | import java.io.IOException; 16 | import java.util.function.UnaryOperator; 17 | 18 | /** 19 | * 20 | * @author jbred 21 | * 22 | */ 23 | public final class WhitelistConfigHandler 24 | { 25 | @Nonnull 26 | private static final String error = "An error occurred while parsing a whitelist entry in file \"%s\", skipping..."; 27 | public static void init(@Nonnull final JsonObject configs) throws IOException { 28 | // run for auto configs, mod instances, and user config 29 | FluidloggedAPIConfigs.forEach(configs, "WHITELIST", "whitelist", (file, jsonIn) -> { 30 | try { ConfigPredicate.deserialize(file, jsonIn.getAsJsonObject(), IConfigAccessor::getWhitelistPredicate, IConfigAccessor::setWhitelistAndCache, UnaryOperator.identity()); } 31 | catch(@Nonnull final Throwable t) { FluidloggedAPI.LOGGER.error(String.format(error, file), t); } 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/config/util/ConfigPredicateOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.config.util; 7 | 8 | import com.google.gson.JsonParseException; 9 | 10 | import javax.annotation.Nonnull; 11 | import java.util.function.BiFunction; 12 | 13 | /** 14 | * 15 | * @author jbred 16 | * 17 | */ 18 | public enum ConfigPredicateOperation implements BiFunction 19 | { 20 | always { 21 | @Nonnull 22 | @Override 23 | public ConfigPredicate apply(@Nonnull final ConfigPredicate original, ConfigPredicate replacement) { 24 | return replacement; 25 | } 26 | }, 27 | and { 28 | @Nonnull 29 | @Override 30 | public ConfigPredicate apply(@Nonnull final ConfigPredicate original, ConfigPredicate replacement) { 31 | return (world, pos, state, fluid) -> original.test(world, pos, state, fluid) && replacement.test(world, pos, state, fluid); 32 | } 33 | }, 34 | never { 35 | @Nonnull 36 | @Override 37 | public ConfigPredicate apply(@Nonnull final ConfigPredicate original, ConfigPredicate replacement) { 38 | return original; 39 | } 40 | }, 41 | or { 42 | @Nonnull 43 | @Override 44 | public ConfigPredicate apply(@Nonnull final ConfigPredicate original, ConfigPredicate replacement) { 45 | return (world, pos, state, fluid) -> original.test(world, pos, state, fluid) || replacement.test(world, pos, state, fluid); 46 | } 47 | }; 48 | 49 | @Nonnull 50 | public static ConfigPredicateOperation get(@Nonnull final String nameIn) { 51 | for(@Nonnull final ConfigPredicateOperation op : values()) if(op.name().equals(nameIn)) return op; 52 | throw new JsonParseException("Could not get config predicate replacement operation from: \"" + nameIn + "\". Valid operations are: [always (default), and, never, or]."); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/datafix/FluidloggedAPIFixableData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.datafix; 7 | 8 | import git.jbredwards.fluidlogged_api.api.capability.IFluidStateCapability; 9 | import net.minecraft.nbt.NBTTagCompound; 10 | import net.minecraft.nbt.NBTTagList; 11 | import net.minecraft.util.datafix.IFixableData; 12 | import net.minecraftforge.common.util.Constants; 13 | 14 | import javax.annotation.Nonnull; 15 | 16 | /** 17 | * 18 | * @author jbred 19 | * 20 | */ 21 | public final class FluidloggedAPIFixableData implements IFixableData 22 | { 23 | /** 24 | * The current data version. 25 | */ 26 | @Override 27 | public int getFixVersion() { return DATA_VERSION; } 28 | public static final int DATA_VERSION = 103; 29 | 30 | @Nonnull 31 | @Override 32 | public NBTTagCompound fixTagCompound(@Nonnull final NBTTagCompound compound) { 33 | return ToFluidloggedDataFixer.fix(LegacyDataFixer.fix(compound)); 34 | } 35 | 36 | @Nonnull 37 | public static NBTTagList getOrCreateFluidCapabilityData(@Nonnull final NBTTagCompound level) { 38 | // initialize or get forge capability nbt 39 | @Nonnull final NBTTagCompound forgeCaps; 40 | if(level.hasKey("ForgeCaps", Constants.NBT.TAG_COMPOUND)) forgeCaps = level.getCompoundTag("ForgeCaps"); 41 | else level.setTag("ForgeCaps", forgeCaps = new NBTTagCompound()); 42 | 43 | // initialize or get IFluidStateCapability nbt 44 | @Nonnull final NBTTagList cap; 45 | @Nonnull final String capID = IFluidStateCapability.CAPABILITY_ID.toString(); 46 | if(forgeCaps.hasKey(capID, Constants.NBT.TAG_COMPOUND)) { // respect modern data if present 47 | final NBTTagCompound capNBT = forgeCaps.getCompoundTag(capID); 48 | capNBT.setTag("data", cap = capNBT.getTagList("data", Constants.NBT.TAG_COMPOUND)); 49 | } 50 | else forgeCaps.setTag(capID, cap = forgeCaps.getTagList(capID, Constants.NBT.TAG_COMPOUND)); 51 | 52 | // return generated 53 | return cap; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/datafix/modded/DynamicTreesDataFixer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.datafix.modded; 7 | 8 | import com.ferreusveritas.dynamictrees.blocks.BlockRootyWater; 9 | import git.jbredwards.fluidlogged_api.api.datafix.FluidMappingData; 10 | import git.jbredwards.fluidlogged_api.api.datafix.IFluidloggedDataMapper; 11 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 12 | import net.minecraftforge.fluids.FluidRegistry; 13 | import net.minecraftforge.fml.common.registry.ForgeRegistries; 14 | 15 | import javax.annotation.Nonnull; 16 | 17 | /** 18 | * 19 | * @author jbred 20 | * 21 | */ 22 | public enum DynamicTreesDataFixer implements IFluidloggedDataMapper 23 | { 24 | INSTANCE; 25 | 26 | public static void register() { 27 | ForgeRegistries.BLOCKS.getValuesCollection().stream() 28 | .filter(block -> block instanceof BlockRootyWater) 29 | .forEach(block -> MAPPERS.put(block, INSTANCE)); 30 | } 31 | 32 | @Nonnull 33 | @Override 34 | public FluidMappingData remapFluidData(final int blockID, final int blockMetadata) { 35 | return new FluidMappingData(FluidState.of(FluidRegistry.WATER)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/datafix/modded/TropicraftDataFixer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.datafix.modded; 7 | 8 | import git.jbredwards.fluidlogged_api.api.datafix.FluidMappingData; 9 | import git.jbredwards.fluidlogged_api.api.datafix.IFluidloggedDataMapper; 10 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 11 | import net.tropicraft.core.registry.BlockRegistry; 12 | 13 | import javax.annotation.Nonnull; 14 | 15 | /** 16 | * 17 | * @author jbred 18 | * 19 | */ 20 | public enum TropicraftDataFixer implements IFluidloggedDataMapper 21 | { 22 | INSTANCE; 23 | 24 | public static void register() { 25 | MAPPERS.put(BlockRegistry.bambooFence, INSTANCE); 26 | MAPPERS.put(BlockRegistry.chunkFence, INSTANCE); 27 | MAPPERS.put(BlockRegistry.mahoganyFence, INSTANCE); 28 | MAPPERS.put(BlockRegistry.palmFence, INSTANCE); 29 | MAPPERS.put(BlockRegistry.thatchFence, INSTANCE); 30 | } 31 | 32 | @Nonnull 33 | @Override 34 | public FluidMappingData remapFluidData(final int blockID, final int blockMetadata) { 35 | return new FluidMappingData(blockMetadata < 2 ? FluidState.of(BlockRegistry.tropicsWater) : FluidState.EMPTY).withMetadata(0); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/fluid/util/impl/SpecializedFluidNeighborInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.fluid.util.impl; 7 | 8 | import git.jbredwards.fluidlogged_api.api.util.FluidState; 9 | import git.jbredwards.fluidlogged_api.mod.common.fluid.util.ISpecializedFluidNeighborInfo; 10 | import net.minecraft.block.Block; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.world.IBlockAccess; 13 | 14 | import javax.annotation.Nonnull; 15 | import javax.annotation.Nullable; 16 | import java.util.Map; 17 | 18 | /** 19 | * 20 | * @author jbred 21 | * 22 | */ 23 | public abstract class SpecializedFluidNeighborInfo extends FluidNeighborInfo implements ISpecializedFluidNeighborInfo 24 | { 25 | public static class Forge extends SpecializedFluidNeighborInfo implements ISpecializedFluidNeighborInfo.Forge 26 | { 27 | public Forge(@Nonnull final IBlockAccess accessIn, @Nonnull final BlockPos originIn, @Nonnull final FluidState originStateIn, final int radius) { 28 | super(accessIn, originIn, originStateIn, radius); 29 | } 30 | } 31 | 32 | public static class Vanilla extends SpecializedFluidNeighborInfo implements ISpecializedFluidNeighborInfo.Vanilla 33 | { 34 | public Vanilla(@Nonnull final IBlockAccess accessIn, @Nonnull final BlockPos originIn, @Nonnull final FluidState originStateIn, final int radius) { 35 | super(accessIn, originIn, originStateIn, radius); 36 | } 37 | } 38 | 39 | // @Nonnull public final Boolean[] isFluidloggable; 40 | // @Nonnull public final Boolean[] isReplaceable; 41 | 42 | @Nullable public Boolean doFireTick; 43 | public SpecializedFluidNeighborInfo(@Nonnull final IBlockAccess accessIn, @Nonnull final BlockPos originIn, @Nonnull final FluidState originStateIn, final int radius) { 44 | super(accessIn, originIn, originStateIn, radius); 45 | // final int size = 16 * cache.diamXZ * cache.diamY * cache.diamXZ; 46 | // isFluidloggable = new Boolean[size]; 47 | // isReplaceable = new Boolean[size]; 48 | } 49 | 50 | @Nonnull 51 | @Override 52 | public Boolean setDoFireTick(@Nonnull final Boolean doFireTickIn) { return doFireTick = doFireTickIn; } 53 | 54 | // ------- 55 | // getters 56 | // ------- 57 | 58 | @Nullable 59 | @Override 60 | public Boolean getDoFireTick() { return doFireTick; } 61 | 62 | /*@Nonnull 63 | @Override 64 | public Boolean[] getIsFluidloggable() { return isFluidloggable; } 65 | 66 | @Nonnull 67 | @Override 68 | public Boolean[] getIsReplaceable() { return isReplaceable; }*/ 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/message/CMessageSyncGameRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.message; 7 | 8 | import git.jbredwards.fluidlogged_api.api.network.message.AbstractMessage; 9 | import net.minecraft.network.PacketBuffer; 10 | import net.minecraft.world.GameRules; 11 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 12 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 13 | 14 | import javax.annotation.Nonnull; 15 | import javax.annotation.Nullable; 16 | 17 | /** 18 | * 19 | * @author jbred 20 | * 21 | */ 22 | public final class CMessageSyncGameRule extends AbstractMessage 23 | { 24 | public String gameRuleId; 25 | public boolean updateRender; 26 | 27 | public CMessageSyncGameRule() {} 28 | public CMessageSyncGameRule(@Nonnull final String gameRuleIdIn, final boolean updateRenderIn) { 29 | isValid = true; 30 | gameRuleId = gameRuleIdIn; 31 | updateRender = updateRenderIn; 32 | } 33 | 34 | @Override 35 | public void read(@Nonnull final PacketBuffer buf) { 36 | gameRuleId = buf.readString(Short.MAX_VALUE); 37 | updateRender = buf.readBoolean(); 38 | } 39 | 40 | @Override 41 | public void write(@Nonnull final PacketBuffer buf) { buf.writeString(gameRuleId).writeBoolean(updateRender); } 42 | public enum Handler implements IMessageHandler 43 | { 44 | INSTANCE; 45 | 46 | @Nullable 47 | @Override 48 | public SMessageSyncGameRule onMessage(@Nonnull final CMessageSyncGameRule message, @Nonnull final MessageContext ctx) { 49 | if(!message.isValid || !ctx.side.isServer()) return null; 50 | 51 | @Nonnull final GameRules gameRules = ctx.getServerHandler().player.world.getGameRules(); 52 | return new SMessageSyncGameRule(message.gameRuleId, gameRules.getString(message.gameRuleId), message.updateRender); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/message/SMessageSyncGameRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.message; 7 | 8 | import git.jbredwards.fluidlogged_api.api.network.IClientMessageHandler; 9 | import git.jbredwards.fluidlogged_api.api.network.message.AbstractMessage; 10 | import net.minecraft.client.Minecraft; 11 | import net.minecraft.network.PacketBuffer; 12 | import net.minecraft.world.GameRules; 13 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 14 | import net.minecraftforge.fml.relauncher.Side; 15 | import net.minecraftforge.fml.relauncher.SideOnly; 16 | 17 | import javax.annotation.Nonnull; 18 | 19 | /** 20 | * 21 | * @author jbred 22 | * 23 | */ 24 | public final class SMessageSyncGameRule extends AbstractMessage 25 | { 26 | public String gameRuleId, gameRuleValue; 27 | public boolean updateRender; 28 | 29 | public SMessageSyncGameRule() {} 30 | public SMessageSyncGameRule(@Nonnull final String gameRuleIdIn, @Nonnull final String gameRuleValueIn, final boolean updateRenderIn) { 31 | isValid = true; 32 | gameRuleId = gameRuleIdIn; 33 | gameRuleValue = gameRuleValueIn; 34 | updateRender = updateRenderIn; 35 | } 36 | 37 | @Override 38 | public void read(@Nonnull final PacketBuffer buf) { 39 | gameRuleId = buf.readString(Short.MAX_VALUE); 40 | gameRuleValue = buf.readString(Short.MAX_VALUE); 41 | updateRender = buf.readBoolean(); 42 | } 43 | 44 | @Override 45 | public void write(@Nonnull final PacketBuffer buf) { 46 | buf.writeString(gameRuleId).writeString(gameRuleValue).writeBoolean(updateRender); 47 | } 48 | 49 | public enum Handler implements IClientMessageHandler 50 | { 51 | INSTANCE; 52 | 53 | @SideOnly(Side.CLIENT) 54 | @Override 55 | public void handleMessage(@Nonnull final SMessageSyncGameRule message, @Nonnull final MessageContext ctx) { 56 | @Nonnull final GameRules gameRules = IClientMessageHandler.getWorldFromContext(ctx).getGameRules(); 57 | if(message.updateRender && !gameRules.getString(message.gameRuleId).equals(message.gameRuleValue)) { 58 | // Minecraft.getMinecraft().ingameGUI.setOverlayMessage(I18n.format(""), false); 59 | Minecraft.getMinecraft().renderGlobal.loadRenderers(); 60 | } 61 | 62 | gameRules.setOrCreateGameRule(message.gameRuleId, message.gameRuleValue); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/message/SMessageSyncRuntimeConfigs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.message; 7 | 8 | import com.google.gson.Gson; 9 | import com.google.gson.JsonObject; 10 | import com.google.gson.JsonParser; 11 | import git.jbredwards.fluidlogged_api.api.network.IClientMessageHandler; 12 | import git.jbredwards.fluidlogged_api.api.network.message.AbstractMessage; 13 | import git.jbredwards.fluidlogged_api.mod.common.config.FluidloggedAPIConfigs; 14 | import io.netty.buffer.ByteBufInputStream; 15 | import io.netty.buffer.ByteBufOutputStream; 16 | import net.minecraft.network.PacketBuffer; 17 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 18 | import net.minecraftforge.fml.relauncher.Side; 19 | import net.minecraftforge.fml.relauncher.SideOnly; 20 | 21 | import javax.annotation.Nonnull; 22 | import java.io.*; 23 | import java.nio.charset.StandardCharsets; 24 | 25 | /** 26 | * 27 | * @author jbred 28 | * 29 | */ 30 | public final class SMessageSyncRuntimeConfigs extends AbstractMessage 31 | { 32 | @Nonnull 33 | private static final Gson GSON = new Gson(); 34 | 35 | public JsonObject configs; 36 | public SMessageSyncRuntimeConfigs() {} 37 | public SMessageSyncRuntimeConfigs(@Nonnull final JsonObject configsIn) { 38 | isValid = true; 39 | configs = configsIn; 40 | } 41 | 42 | @Override 43 | public void read(@Nonnull final PacketBuffer buf) { 44 | try(@Nonnull final Reader reader = new InputStreamReader(new ByteBufInputStream(buf, buf.readInt()), StandardCharsets.UTF_8)) 45 | { configs = new JsonParser().parse(reader).getAsJsonObject(); } 46 | catch (@Nonnull final IOException ignored) {} 47 | } 48 | 49 | @Override 50 | public void write(@Nonnull final PacketBuffer buf) { 51 | buf.writeInt(0); // allocate size bytes 52 | final int startIndex = buf.writerIndex(); 53 | 54 | try(@Nonnull final Writer writer = new OutputStreamWriter(new ByteBufOutputStream(buf), StandardCharsets.UTF_8)) 55 | { GSON.toJson(configs, writer); } 56 | catch (@Nonnull final IOException ignored) {} 57 | 58 | buf.setInt(startIndex - 4, buf.writerIndex() - startIndex); // write size to allocated bytes 59 | } 60 | 61 | public enum Handler implements IClientMessageHandler 62 | { 63 | INSTANCE; 64 | 65 | @SideOnly(Side.CLIENT) 66 | @Override 67 | public void handleMessage(@Nonnull final SMessageSyncRuntimeConfigs message, @Nonnull final MessageContext ctx) throws Exception { 68 | FluidloggedAPIConfigs.init(message.configs); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/git/jbredwards/fluidlogged_api/mod/common/message/SMessageVaporizeEffects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024-2025. jbredwards 3 | * All rights reserved. 4 | */ 5 | 6 | package git.jbredwards.fluidlogged_api.mod.common.message; 7 | 8 | import git.jbredwards.fluidlogged_api.api.network.IClientMessageHandler; 9 | import git.jbredwards.fluidlogged_api.api.network.message.AbstractMessage; 10 | import net.minecraft.nbt.NBTTagCompound; 11 | import net.minecraft.network.PacketBuffer; 12 | import net.minecraft.util.math.BlockPos; 13 | import net.minecraftforge.fluids.FluidStack; 14 | import net.minecraftforge.fml.common.network.ByteBufUtils; 15 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 16 | import net.minecraftforge.fml.relauncher.Side; 17 | import net.minecraftforge.fml.relauncher.SideOnly; 18 | 19 | import javax.annotation.Nonnull; 20 | 21 | /** 22 | * play fluid vaporize effects for the client from the server 23 | * @author jbred 24 | * 25 | */ 26 | public final class SMessageVaporizeEffects extends AbstractMessage 27 | { 28 | public FluidStack fluid; 29 | public BlockPos pos; 30 | 31 | public SMessageVaporizeEffects() {} 32 | public SMessageVaporizeEffects(@Nonnull FluidStack fluidIn, @Nonnull BlockPos posIn) { 33 | fluid = fluidIn; 34 | pos = posIn; 35 | isValid = true; 36 | } 37 | 38 | @Override 39 | public void read(@Nonnull PacketBuffer buf) { 40 | fluid = FluidStack.loadFluidStackFromNBT(ByteBufUtils.readTag(buf)); 41 | pos = buf.readBlockPos(); 42 | } 43 | 44 | @Override 45 | public void write(@Nonnull PacketBuffer buf) { 46 | buf.writeCompoundTag(fluid.writeToNBT(new NBTTagCompound())); 47 | buf.writeBlockPos(pos); 48 | } 49 | 50 | public enum Handler implements IClientMessageHandler 51 | { 52 | INSTANCE; 53 | 54 | @SideOnly(Side.CLIENT) 55 | @Override 56 | public void handleMessage(@Nonnull final SMessageVaporizeEffects message, @Nonnull final MessageContext ctx) { 57 | message.fluid.getFluid().vaporize(null, IClientMessageHandler.getWorldFromContext(ctx), message.pos, message.fluid); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/fluidlogged_api_at.cfg: -------------------------------------------------------------------------------- 1 | # Classes 2 | public net.minecraft.world.biome.BiomeColorHelper$ColorResolver 3 | 4 | # Fields 5 | public net.minecraft.client.network.NetHandlerPlayClient field_147300_g # world 6 | public net.minecraft.client.renderer.block.statemap.BlockStateMapper field_178449_b # setBuiltInBlocks 7 | public net.minecraft.block.Block field_149783_u # useNeighborBrightness 8 | public net.minecraft.entity.item.EntityBoat field_184465_aD # waterLevel 9 | public net.minecraft.entity.EntityLivingBase field_70703_bu # isJumping 10 | public net.minecraft.item.ItemBucket field_77876_a # containedBlock 11 | public-f net.minecraft.world.biome.BiomeColorHelper field_180290_c # WATER_COLOR 12 | public net.minecraft.world.chunk.BlockStateContainer field_186020_a # AIR_BLOCK_STATE 13 | public net.minecraft.world.chunk.Chunk field_76638_b # precipitationHeightMap 14 | public net.minecraft.world.World field_147481_N # processingLoadedTiles 15 | 16 | # Methods 17 | public net.minecraft.block.BlockLiquid func_180688_d(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)V # triggerMixEffects 18 | public net.minecraft.block.BlockLiquid func_189543_a(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)Lnet/minecraft/util/math/Vec3d; # getFlow 19 | public net.minecraft.entity.item.EntityBoat func_184446_u()Z # checkInWater 20 | public net.minecraft.entity.item.EntityBoat func_184444_v()Lnet/minecraft/entity/item/EntityBoat$Status; # getUnderwaterStatus 21 | public net.minecraft.item.Item func_194125_a(Lnet/minecraft/creativetab/CreativeTabs;)Z # isInCreativeTab 22 | public net.minecraft.nbt.NBTUtil func_190010_a(Lnet/minecraft/block/properties/IProperty;Ljava/lang/Comparable;)Ljava/lang/String; # getName 23 | public net.minecraft.world.chunk.Chunk func_76595_e(II)V # propagateSkylightOcclusion 24 | public net.minecraft.world.chunk.Chunk func_76615_h(III)V # relightBlock 25 | public net.minecraft.world.chunk.ChunkPrimer func_186137_b(III)I # getBlockIndex 26 | public net.minecraft.world.World func_175663_a(IIIIIIZ)Z # isAreaLoaded 27 | public net.minecraft.world.World func_189508_F(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity; # getPendingTileEntityAt -------------------------------------------------------------------------------- /src/main/resources/assets/fluidlogged_api/fluidlogged_api/fluidTags.jsonc: -------------------------------------------------------------------------------- 1 | // default fluid tags 2 | [ 3 | { 4 | "id": "builtin:material_lava", 5 | "fluids": {"materialId": "lava"} 6 | }, 7 | { 8 | "id": "builtin:material_water", 9 | "fluids": {"materialId": "water"} 10 | } 11 | ] -------------------------------------------------------------------------------- /src/main/resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbredwards/Fluidlogged-API/42129e74dd3d8e3797cf5d907ecfb68fa35daf20/src/main/resources/logo.png -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [{ 2 | "modid": "fluidlogged_api", 3 | "name": "Fluidlogged API", 4 | "description": "mod.fluidlogged_api.description", 5 | "version": "${mod_version}", 6 | "mcversion": "1.12.2", 7 | "logoFile": "logo.png", 8 | "url": "https://github.com/jbredwards/Fluidlogged-API", 9 | "authorList": ["jbredwards"], 10 | "credits": "mod.fluidlogged_api.credits" 11 | }] -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "examplemod resources", 4 | "pack_format": 3 5 | } 6 | } 7 | --------------------------------------------------------------------------------