Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fabric Transfer API: "fluid only" edition #1356

Merged
merged 62 commits into from
Jul 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
b97e358
Original fluid API design
Technici4n Mar 9, 2021
675fba7
Rework the transaction system
Technici4n Mar 9, 2021
2a70d38
First javadoc pass
Technici4n Mar 9, 2021
54e8d90
Add a testmod, a base implementation for fluid storages and fix some …
Technici4n Mar 11, 2021
c2df290
Fix checkstyle
Technici4n Mar 11, 2021
07ccb3e
Make Movement#move extract from the view and not the whole Storage
Technici4n Mar 31, 2021
71c9e84
Document and update FluidPreconditions
Technici4n Mar 31, 2021
0a6e496
Use for-each in CombinedStorage and document a little
Technici4n Mar 31, 2021
f396aaf
Remove useless overrides in Insertion/ExtractionOnlyStorage
Technici4n Mar 31, 2021
9b5d7eb
Move SnapshotParticipant#snapshots to the top of the class, and make …
Technici4n Mar 31, 2021
f8726a6
Fix garbage collection of unused CauldronWrappers
Technici4n Mar 31, 2021
ab411aa
Use ArrayList directly
Technici4n Mar 31, 2021
75a71e2
Remove locking, reorganize transaction implementation, and add outer …
Technici4n Apr 7, 2021
2d5b710
Add more javadoc
Technici4n Apr 10, 2021
8645932
Rework Storage#forEach into Storage#iterator
Technici4n Apr 15, 2021
5f5a322
Add a few missing `transaction.addCloseCallback(iterator)`
Technici4n Apr 15, 2021
40adaa0
Add anyView(), exactView(), capacity() and isEmpty()
Technici4n May 24, 2021
37b06de
Add Storage#iterable to make iteration friendlier to for loops
Technici4n May 26, 2021
e6c9d03
Storages may now have multiple open iterators
Technici4n May 29, 2021
ea312bb
Make CombinedStorage#supportsInsertion/Extraction iterate through the…
Technici4n May 29, 2021
5c76a41
Block updates should be used when the supportsInsertion/Extraction st…
Technici4n May 29, 2021
caa30e3
Fluid -> FluidKey
Technici4n May 31, 2021
ad09993
Remove all references to ItemKey inside FluidKey, and other minor tweaks
Technici4n May 31, 2021
c7cd30d
Cache FluidKeys with a null tag inside Fluid directly
Technici4n May 31, 2021
efe1aca
Fluid unit convention
Technici4n May 31, 2021
2f45802
Add FluidKeyRendering and RenderHandler
Technici4n May 31, 2021
317f648
Bump version for more testing (also published to my maven)
Technici4n May 31, 2021
e5986aa
Add SingleViewIterator, massively reduce code duplication!
Technici4n Jun 1, 2021
6fca9e6
Make API experimental, and add README
Technici4n Jun 5, 2021
95015a2
Bump version
Technici4n Jun 5, 2021
115d959
Apparently Fluids.EMPTY is flowing
Technici4n Jun 5, 2021
47488d6
Add package info
Technici4n Jun 6, 2021
6397c9c
Minor adjustements
Technici4n Jun 6, 2021
5ed9b48
1.17 port, cauldron support, add ResourceKey
Technici4n Jun 14, 2021
fd2384e
Checkstyle, gas rendering, use record for ResourceAmount
Technici4n Jun 17, 2021
3051d4a
Add a few helpers, rename some stuff
Technici4n Jun 19, 2021
a1898b8
Remove anyView, allow nullable in StorageUtil#find*, fix missing try …
Technici4n Jun 20, 2021
dc8ad43
Slight findStoredResource cleanup
liach Jun 20, 2021
8ddc5d2
Slightly improve implementation
Technici4n Jun 23, 2021
feb3e2d
Bump version
Technici4n Jun 24, 2021
8460a96
Fix wrong transaction
Technici4n Jun 24, 2021
f08617f
I wrote in a comment that this could happen...
Technici4n Jun 24, 2021
05ece40
Fix SingleFluidStorage bugs, add tests in the testmod, add testmod as…
Technici4n Jun 26, 2021
639198d
Add extract stick
Technici4n Jun 26, 2021
4412b88
Rename a few things
Technici4n Jun 28, 2021
d2bac40
Bump version
Technici4n Jun 29, 2021
f9e7ad8
FluidKey -> FluidVariant
Technici4n Jun 30, 2021
9490060
Bump version
Technici4n Jul 2, 2021
0d3983f
Expand getVersion() documentation, make it thread-safe and use long.
Technici4n Jul 4, 2021
b81c12e
empty resource -> blank resource, and update SingleFluidStorage
Technici4n Jul 4, 2021
14692d1
Make CauldronFluidContent a final class instead of a record.
Technici4n Jul 4, 2021
5ea73c2
Get rid of CauldronFluidContent#minLevel (was always 1)
Technici4n Jul 4, 2021
0e0a933
Fix nested commits. (Thanks @warjort!)
Technici4n Jul 4, 2021
010171a
Separate Transaction and TransactionContext
Technici4n Jul 5, 2021
8f5b76a
Change WorldLocation into a private record
Technici4n Jul 5, 2021
a2b81c1
Bump version
Technici4n Jul 5, 2021
a849e94
Guard against exceptions thrown in close callbacks
Technici4n Jul 6, 2021
c0d2a77
Make sure blank fluid variants don't have a tag
Technici4n Jul 7, 2021
76e95bb
Add documentation, make CauldronStorage clearer
Technici4n Jul 9, 2021
c0052c7
Allow null storages in StorageUtil#move, and clarify sidedness of Flu…
Technici4n Jul 9, 2021
aa7c2bf
Add explicit hashCode and equals for transfer variants
Technici4n Jul 10, 2021
200aa09
Remove ugly equals and hashCode overrides, and add constant time hash…
Technici4n Jul 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ allprojects {

checkstyle {
configFile = rootProject.file("checkstyle.xml")
toolVersion = "8.31"
toolVersion = "8.43"
}

tasks.withType(AbstractArchiveTask) {
Expand Down
36 changes: 36 additions & 0 deletions fabric-transfer-api-v1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Fabric Transfer API (v1)
This module provides common facilities for the transfer of fluids and other game resources.

## Transactions
The [`Transaction`](src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/Transaction.java) system provides a
scope that can be used to simulate any number of transfer operations, and then cancel or validate all of them at once.
One can think of transactions as video game checkpoints. A more detailed explanation can be found in the class javadoc of `Transaction`.
Every transfer operation requires a `Transaction` parameter.
[`SnapshotParticipant`](src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java)
is the reference implementation of a "participant", that is an object participating in a transaction.

## Storages
A [`Storage<T>`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Storage.java) is any object that can store resources of type `T`.
Its contents can be read, and resources can be inserted into it or extracted from it.
[`StorageUtil`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/StorageUtil.java) provides a few helpful functions to work with `Storage`s,
for example to move resources between two `Storage`s.
The [`storage/base`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base) package provides a few helpers to accelerate
implementation of `Storage<T>`.

## Fluid transfer
A `Storage<FluidVariant>` is any object that can store fluids. It is just a `Storage<T>`, where `T` is
[`FluidVariant`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidVariant.java), the immutable combination of a `Fluid` and additional NBT data.
Instances can be accessed through the API lookups defined in [`FluidStorage`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidStorage.java).

Implementors of fluid inventories with a fixed number of "slots" or "tanks" can use
[`SingleFluidStorage`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/base/SingleFluidStorage.java),
and combine them with `CombinedStorage`.

The unit for fluid transfer is 1/81000ths of a bucket, also known as _droplets_.
[`FluidConstants`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidConstants.java) contains a few helpful constants
to work with droplets.

Client-side [Fluid variant rendering](src/main/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRendering.java) will use regular fluid rendering by default,
ignoring the additional NBT data.
`Fluid`s that wish to render differently depending on the stored NBT data can register a
[`FluidVariantRenderHandler`](src/main/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRenderHandler.java).
17 changes: 17 additions & 0 deletions fabric-transfer-api-v1/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
archivesBaseName = "fabric-transfer-api-v1"
version = getSubprojectVersion(project, "0.3.4")

moduleDependencies(project, [
'fabric-api-base',
'fabric-api-lookup-api-v1',
'fabric-lifecycle-events-v1', // transitive dependency of API Lookup
'fabric-rendering-fluids-v1',
'fabric-textures-v0' // transitive dependency of Rendering Fluids
])

dependencies {
testmodImplementation project(path: ':fabric-object-builder-api-v1', configuration: 'dev')
testmodImplementation project(path: ':fabric-resource-loader-v0', configuration: 'dev')
testmodImplementation project(path: ':fabric-tag-extensions-v0', configuration: 'dev')
testmodImplementation project(path: ':fabric-tool-attribute-api-v1', configuration: 'dev')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.transfer.v1.client.fluid;

import java.util.List;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import net.minecraft.client.item.TooltipContext;
import net.minecraft.client.texture.Sprite;
import net.minecraft.text.Text;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;

/**
* Defines how {@linkplain FluidVariant fluid variants} of a given Fluid should be displayed to clients.
* Register with {@link FluidVariantRendering#register}.
*
* @deprecated Experimental feature, we reserve the right to remove or change it without further notice.
* The transfer API is a complex addition, and we want to be able to correct possible design mistakes.
*/
@ApiStatus.Experimental
@Deprecated
@Environment(EnvType.CLIENT)
public interface FluidVariantRenderHandler {
/**
* Return the name that should be used for the passed fluid variant.
*/
default Text getName(FluidVariant fluidVariant) {
return fluidVariant.getFluid().getDefaultState().getBlockState().getBlock().getName();
}

/**
* Append additional tooltips to the passed list if additional information is contained in the fluid variant.
*
* <p>The name of the fluid, and its identifier if the tooltip context is advanced, should not be appended.
* They are already added by {@link FluidVariantRendering#getTooltip}.
*/
default void appendTooltip(FluidVariant fluidVariant, List<Text> tooltip, TooltipContext tooltipContext) {
}

/**
* Return the sprite that should be used to render the passed fluid variant, for use in baked models, (block) entity renderers, or user interfaces.
*
* <p>Null may be returned if the fluid variant should not be rendered.
*/
@Nullable
default Sprite getSprite(FluidVariant fluidVariant) {
// Use the fluid render handler by default.
FluidRenderHandler fluidRenderHandler = FluidRenderHandlerRegistry.INSTANCE.get(fluidVariant.getFluid());

if (fluidRenderHandler != null) {
return fluidRenderHandler.getFluidSprites(null, null, fluidVariant.getFluid().getDefaultState())[0];
} else {
return null;
}
}

/**
* Return the color to use when rendering {@linkplain #getSprite the sprite} of this fluid variant.
*/
default int getColor(FluidVariant fluidVariant) {
// Use the fluid render handler by default.
FluidRenderHandler fluidRenderHandler = FluidRenderHandlerRegistry.INSTANCE.get(fluidVariant.getFluid());

if (fluidRenderHandler != null) {
return fluidRenderHandler.getFluidColor(null, null, fluidVariant.getFluid().getDefaultState());
} else {
return -1;
}
}

/**
* Return {@code true} if this fluid should fill tanks from top.
*/
default boolean fillsFromTop(FluidVariant fluidVariant) {
// By default, fluids should be filled from the bottom.
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.transfer.v1.client.fluid;

import java.util.ArrayList;
import java.util.List;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import net.minecraft.client.item.TooltipContext;
import net.minecraft.client.texture.Sprite;
import net.minecraft.fluid.Fluid;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.registry.Registry;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.lookup.v1.custom.ApiProviderMap;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;

/**
* Client-side display of fluid variants.
*
* @deprecated Experimental feature, we reserve the right to remove or change it without further notice.
* The transfer API is a complex addition, and we want to be able to correct possible design mistakes.
*/
@ApiStatus.Experimental
@Deprecated
@Environment(EnvType.CLIENT)
public class FluidVariantRendering {
private static final ApiProviderMap<Fluid, FluidVariantRenderHandler> HANDLERS = ApiProviderMap.create();
private static final FluidVariantRenderHandler DEFAULT_HANDLER = new FluidVariantRenderHandler() { };

/**
* Register a render handler for the passed fluid.
*/
public static void register(Fluid fluid, FluidVariantRenderHandler handler) {
if (HANDLERS.putIfAbsent(fluid, handler) != null) {
throw new IllegalArgumentException("Duplicate handler registration for fluid " + fluid);
}
}

/**
* Return the render handler for the passed fluid, if available, and {@code null} otherwise.
*/
@Nullable
public static FluidVariantRenderHandler getHandler(Fluid fluid) {
return HANDLERS.get(fluid);
}

/**
* Return the render handler for the passed fluid, if available, or the default instance otherwise.
*/
public static FluidVariantRenderHandler getHandlerOrDefault(Fluid fluid) {
FluidVariantRenderHandler handler = HANDLERS.get(fluid);
return handler == null ? DEFAULT_HANDLER : handler;
}

/**
* Return the name of the passed fluid variant.
*/
public static Text getName(FluidVariant fluidVariant) {
return getHandlerOrDefault(fluidVariant.getFluid()).getName(fluidVariant);
}

/**
* Return the tooltip for the passed fluid variant, including the name and additional lines if available
* and the id of the fluid if advanced tooltips are enabled.
*/
public static List<Text> getTooltip(FluidVariant fluidVariant, TooltipContext context) {
List<Text> tooltip = new ArrayList<>();

// Name first
tooltip.add(getName(fluidVariant));

// Additional tooltip information
getHandlerOrDefault(fluidVariant.getFluid()).appendTooltip(fluidVariant, tooltip, context);

// If advanced tooltips are enabled, render the fluid id
if (context.isAdvanced()) {
tooltip.add(new LiteralText(Registry.FLUID.getId(fluidVariant.getFluid()).toString()).formatted(Formatting.DARK_GRAY));
}

// TODO: consider adding an event to append to tooltips?

return tooltip;
}

/**
* Return the sprite that should be used to render the passed fluid variant, or null if it's not available.
* The sprite should be rendered using the color returned by {@link #getColor}.
*/
@Nullable
public static Sprite getSprite(FluidVariant fluidVariant) {
return getHandlerOrDefault(fluidVariant.getFluid()).getSprite(fluidVariant);
}

/**
* Return the color that should be used to render {@linkplain #getSprite the sprite} of the passed fluid variant.
*/
public static int getColor(FluidVariant fluidVariant) {
return getHandlerOrDefault(fluidVariant.getFluid()).getColor(fluidVariant);
}

/**
* Return {@code true} if this fluid variant should be rendered as filling tanks from the top.
*/
public static boolean fillsFromTop(FluidVariant fluidVariant) {
return getHandlerOrDefault(fluidVariant.getFluid()).fillsFromTop(fluidVariant);
}
}
Loading