Skip to content

Commit

Permalink
Re-add fluid variants
Browse files Browse the repository at this point in the history
The implementations in FluidStack regarding components is a stab for what the future api could be, and will definitely change.

Signed-off-by: shedaniel <[email protected]>
  • Loading branch information
shedaniel committed Mar 1, 2024
1 parent 7b65d8d commit 8d0fdbd
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 190 deletions.
207 changes: 143 additions & 64 deletions common/src/main/java/dev/architectury/fluid/FluidStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,38 @@

package dev.architectury.fluid;

import com.google.common.collect.Iterators;
import com.mojang.serialization.Codec;
import dev.architectury.hooks.fluid.FluidStackHooks;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.core.Holder;
import net.minecraft.core.component.*;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

public final class FluidStack {
public final class FluidStack implements DataComponentHolder {
private static final FluidStackAdapter<Object> ADAPTER = adapt(FluidStack::getValue, FluidStack::new);
private static final FluidStack EMPTY = create(Fluids.EMPTY, 0);
public static final Codec<FluidStack> CODEC = ADAPTER.codec();
public static final StreamCodec<RegistryFriendlyByteBuf, FluidStack> STREAM_CODEC = ADAPTER.streamCodec();

private Object value;
private final Object value;

private FluidStack(Supplier<Fluid> fluid, long amount, CompoundTag tag) {
this(ADAPTER.create(fluid, amount, tag));
private FluidStack(Supplier<Fluid> fluid, long amount, DataComponentPatch patch) {
this(ADAPTER.create(fluid, amount, patch));
}

private FluidStack(Object value) {
Expand All @@ -57,9 +66,103 @@ private static FluidStackAdapter<Object> adapt(Function<FluidStack, Object> toVa
throw new AssertionError();
}

@Override
public DataComponentMap getComponents() {
return new DataComponentMap() {
@Nullable
@Override
public <T> T get(DataComponentType<? extends T> type) {
return getPatch().get(type).orElse(null);
}

@Override
public Set<DataComponentType<?>> keySet() {
return new AbstractSet<>() {
@Override
public Iterator<DataComponentType<?>> iterator() {
return Iterators.transform(getPatch().entrySet().iterator(), Map.Entry::getKey);
}

@Override
public int size() {
return getPatch().entrySet().size();
}

@Override
public boolean contains(Object o) {
if (!(o instanceof DataComponentType<?> type)) return false;
return getPatch().get(type).isPresent();
}
};
}
};
}

public <T> T set(DataComponentType<? super T> dataComponentType, @Nullable T object) {
T previous = (T) get(dataComponentType);
DataComponentPatch.Builder builder = DataComponentPatch.builder();
for (TypedDataComponent<?> component : getComponents()) {
if (component.type() != dataComponentType) {
builder.set(component);
}
}
if (object != null) {
builder.set(dataComponentType, object);
}
setPatch(builder.build());
return previous;
}

@Nullable
public <T, U> T update(DataComponentType<T> dataComponentType, T object, U object2, BiFunction<T, U, T> biFunction) {
return this.set(dataComponentType, biFunction.apply(this.getOrDefault(dataComponentType, object), object2));
}

@Nullable
public <T> T update(DataComponentType<T> dataComponentType, T object, UnaryOperator<T> unaryOperator) {
return this.set(dataComponentType, unaryOperator.apply(this.getOrDefault(dataComponentType, object)));
}

@Nullable
public <T> T remove(DataComponentType<? extends T> dataComponentType) {
return this.set(dataComponentType, null);
}

public void applyComponents(DataComponentPatch dataComponentPatch) {
DataComponentPatch.Builder builder = DataComponentPatch.builder();
for (TypedDataComponent<?> component : getComponents()) {
builder.set(component);
}
for (Map.Entry<DataComponentType<?>, Optional<?>> entry : dataComponentPatch.entrySet()) {
if (entry.getValue().isPresent()) {
//noinspection rawtypes
builder.set((DataComponentType) entry.getKey(), entry.getValue().get());
} else {
builder.remove(entry.getKey());
}
}
setPatch(builder.build());
}

public void applyComponents(DataComponentMap dataComponentMap) {
DataComponentPatch.Builder builder = DataComponentPatch.builder();
for (TypedDataComponent<?> component : getComponents()) {
builder.set(component);
}
for (TypedDataComponent<?> entry : dataComponentMap) {
if (entry.value() != null) {
//noinspection rawtypes
builder.set((DataComponentType) entry.type(), entry.value());
} else {
builder.remove(entry.type());
}
}
setPatch(builder.build());
}

@ApiStatus.Internal
public interface FluidStackAdapter<T> {
T create(Supplier<Fluid> fluid, long amount, CompoundTag tag);
T create(Supplier<Fluid> fluid, long amount, @Nullable DataComponentPatch patch);

Supplier<Fluid> getRawFluidSupplier(T object);

Expand All @@ -69,37 +172,51 @@ public interface FluidStackAdapter<T> {

void setAmount(T object, long amount);

CompoundTag getTag(T value);
DataComponentPatch getPatch(T value);

void setTag(T value, CompoundTag tag);
void setPatch(T value, DataComponentPatch patch);

T copy(T value);

int hashCode(T value);

Codec<FluidStack> codec();

StreamCodec<RegistryFriendlyByteBuf, FluidStack> streamCodec();
}

public static FluidStack empty() {
return EMPTY;
}

public static FluidStack create(Fluid fluid, long amount, @Nullable CompoundTag tag) {
return create(() -> fluid, amount, tag);
public static FluidStack create(Fluid fluid, long amount, DataComponentPatch patch) {
if (fluid == Fluids.EMPTY || amount <= 0) return empty();
return create(() -> fluid, amount, patch);
}

public static FluidStack create(Fluid fluid, long amount) {
return create(fluid, amount, null);
return create(fluid, amount, DataComponentPatch.EMPTY);
}

public static FluidStack create(Supplier<Fluid> fluid, long amount, @Nullable CompoundTag tag) {
return new FluidStack(fluid, amount, tag);
public static FluidStack create(Supplier<Fluid> fluid, long amount, DataComponentPatch patch) {
if (amount <= 0) return empty();
return new FluidStack(fluid, amount, patch);
}

public static FluidStack create(Supplier<Fluid> fluid, long amount) {
return create(fluid, amount, null);
return create(fluid, amount, DataComponentPatch.EMPTY);
}

public static FluidStack create(Holder<Fluid> fluid, long amount, DataComponentPatch patch) {
return create(fluid.value(), amount, patch);
}

public static FluidStack create(Holder<Fluid> fluid, long amount) {
return create(fluid.value(), amount, DataComponentPatch.EMPTY);
}

public static FluidStack create(FluidStack stack, long amount) {
return create(stack.getRawFluidSupplier(), amount, stack.getTag());
return create(stack.getRawFluidSupplier(), amount, stack.getPatch());
}

public static long bucketAmount() {
Expand Down Expand Up @@ -139,50 +256,12 @@ public void shrink(long amount) {
setAmount(getAmount() - amount);
}

public boolean hasTag() {
return getTag() != null;
}

@Nullable
public CompoundTag getTag() {
return ADAPTER.getTag(value);
}

public void setTag(@Nullable CompoundTag tag) {
ADAPTER.setTag(value, tag);
}

public CompoundTag getOrCreateTag() {
CompoundTag tag = getTag();
if (tag == null) {
tag = new CompoundTag();
setTag(tag);
return tag;
}
return tag;
}

@Nullable
public CompoundTag getChildTag(String childName) {
CompoundTag tag = getTag();
if (tag == null)
return null;
return tag.getCompound(childName);
}

public CompoundTag getOrCreateChildTag(String childName) {
CompoundTag tag = getOrCreateTag();
var child = tag.getCompound(childName);
if (!tag.contains(childName, Tag.TAG_COMPOUND)) {
tag.put(childName, child);
}
return child;
public DataComponentPatch getPatch() {
return ADAPTER.getPatch(value);
}

public void removeChildTag(String childName) {
CompoundTag tag = getTag();
if (tag != null)
tag.remove(childName);
public void setPatch(DataComponentPatch patch) {
ADAPTER.setPatch(value, patch);
}

public Component getName() {
Expand Down Expand Up @@ -211,17 +290,17 @@ public boolean equals(Object o) {
}

public boolean isFluidStackEqual(FluidStack other) {
return getFluid() == other.getFluid() && getAmount() == other.getAmount() && isTagEqual(other);
return getFluid() == other.getFluid() && getAmount() == other.getAmount() && isComponentEqual(other);
}

public boolean isFluidEqual(FluidStack other) {
return getFluid() == other.getFluid();
}

public boolean isTagEqual(FluidStack other) {
var tag = getTag();
var otherTag = other.getTag();
return Objects.equals(tag, otherTag);
public boolean isComponentEqual(FluidStack other) {
var patch = getPatch();
var otherPatch = other.getPatch();
return Objects.equals(patch, otherPatch);
}

public static FluidStack read(FriendlyByteBuf buf) {
Expand All @@ -242,7 +321,7 @@ public CompoundTag write(CompoundTag tag) {

public FluidStack copyWithAmount(long amount) {
if (isEmpty()) return this;
return new FluidStack(getRawFluidSupplier(), amount, getTag());
return new FluidStack(getRawFluidSupplier(), amount, getPatch());
}

@ApiStatus.Internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@
import dev.architectury.utils.Env;
import dev.architectury.utils.EnvExecutor;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributes;
import net.minecraft.world.level.material.FlowingFluid;

public class ArchitecturyFlowingFluidImpl {
public static void addFabricFluidAttributes(FlowingFluid fluid, ArchitecturyFluidAttributes attributes) {
// TODO: FluidVariantAttributes.register(fluid, new ArchitecturyFluidAttributesFabric(attributes));
FluidVariantAttributes.register(fluid, new ArchitecturyFluidAttributesFabric(attributes));
EnvExecutor.runInEnv(Env.CLIENT, () -> () -> Client.run(fluid, attributes));
}

private static class Client {
private static void run(FlowingFluid fluid, ArchitecturyFluidAttributes attributes) {
// TODO: FluidVariantRendering.register(fluid, new ArchitecturyFluidRenderingFabric(attributes));
FluidVariantRendering.register(fluid, new ArchitecturyFluidRenderingFabric(attributes));
FluidRenderHandlerRegistry.INSTANCE.register(fluid, new ArchitecturyFluidRenderingFabric(attributes));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import dev.architectury.core.fluid.ArchitecturyFluidAttributes;
import dev.architectury.fluid.FluidStack;
import dev.architectury.hooks.fluid.fabric.FluidStackHooksFabric;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributeHandler;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.level.Level;
Expand All @@ -30,7 +32,7 @@
import java.util.Optional;

@SuppressWarnings("UnstableApiUsage")
class ArchitecturyFluidAttributesFabric {} /*implements FluidVariantAttributeHandler {
class ArchitecturyFluidAttributesFabric implements FluidVariantAttributeHandler {
private final ArchitecturyFluidAttributes attributes;

public ArchitecturyFluidAttributesFabric(ArchitecturyFluidAttributes attributes) {
Expand Down Expand Up @@ -71,4 +73,4 @@ public int getViscosity(FluidVariant variant, @Nullable Level world) {
public boolean isLighterThanAir(FluidVariant variant) {
return attributes.isLighterThanAir(FluidStackHooksFabric.fromFabric(variant, FluidStack.bucketAmount()));
}
}*/
}
Loading

0 comments on commit 8d0fdbd

Please sign in to comment.