architectury / architectury-api

An intermediary api aimed at easing development of multiplatform mods.
https://discord.architectury.dev/
GNU Lesser General Public License v3.0
315 stars 56 forks source link

No way to make ArchitecturyFlowingFluid.Source and ArchitecturyFlowingFluid.Flowing liquids use the same FluidType (ArchitecturyFluidAttributesForge) #447

Closed digitalseraphim closed 8 months ago

digitalseraphim commented 10 months ago

Minecraft: 1.19.2 Forge: 43.2.23 Architectury: git, 1.19.2 branch

The Source and Flowing instances for the same fluid should be using the same "FluidType", but the constructors generate new ones. I came up with the following solution, but it's a little... "dirty", but it works. I didn't create a PR because my editor messes with all of the whitespace, and it's just a pain to undo. If you want me to do one anyways, I can.

I added caches for the Properties and FluidTypes, using the "attributes" object as the key. I'm currently making an addon for KubeJS to do Fluid Interactions (cobblegen, basaltgen), and this is how I found this, as that system makes heavy use of FluidTypes. I left out the imports and the methods I didn't touch.

public abstract class ArchitecturyFlowingFluid extends ForgeFlowingFluid {
    private final ArchitecturyFluidAttributes attributes;
    private final Supplier<FluidType> forgeType;
    private static final Map<ArchitecturyFluidAttributes, Properties> cachedProperties;
    private static final Map<ArchitecturyFluidAttributes, FluidType> cachedFluidType;
    static {
        cachedProperties = new HashMap<>();
        cachedFluidType = new HashMap<>();
    }

    ArchitecturyFlowingFluid(ArchitecturyFluidAttributes attributes) {
        super(toForgeProperties(attributes));
        this.attributes = attributes;
        this.forgeType = Suppliers.memoize(() -> cachedFluidType.get(attributes));
    }

    private static Properties toForgeProperties(ArchitecturyFluidAttributes attributes) {
        Properties forge = cachedProperties.computeIfAbsent(attributes, (_a) -> {
            FluidType ft = cachedFluidType.computeIfAbsent(attributes,
                (_aa) -> new ArchitecturyFluidAttributesForge(FluidType.Properties.create(), attributes.getSourceFluid(),
                        attributes));
            return new Properties(Suppliers.memoize(() -> ft), attributes::getSourceFluid, attributes::getFlowingFluid);
        });
        forge.slopeFindDistance(attributes.getSlopeFindDistance());
        forge.levelDecreasePerBlock(attributes.getDropOff());
        forge.bucket(() -> MoreObjects.firstNonNull(attributes.getBucketItem(), Items.AIR));
        forge.tickRate(attributes.getTickDelay());
        forge.explosionResistance(attributes.getExplosionResistance());
        forge.block(() -> MoreObjects.firstNonNull(attributes.getBlock(), (LiquidBlock) Blocks.WATER));
        return forge;
    }

Thank you!