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

Create a Fluid Flow API #74

Open
wants to merge 22 commits into
base: 1.20
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cb9a9d7
Fluid Flow API
OroArmor Jan 30, 2022
d8cd6f7
Merge in 1.18
OroArmor Feb 18, 2022
4b4b788
Merge remote-tracking branch 'quilt/1.18' into fluid-flow-api
OroArmor Feb 23, 2022
f143c61
Fix some issues + actually merge
OroArmor Feb 23, 2022
7069a89
Apply suggestions from code review
OroArmor Jun 20, 2022
10329d7
Merge branch '1.19' into fluid-flow-api
OroArmor Jun 20, 2022
977d2ca
Remove direction event system and just use a parameter
OroArmor Jun 20, 2022
741414a
Merge branch '1.19' into fluid-flow-api
OroArmor Jun 20, 2022
9a16e65
Apply suggestions from code review
OroArmor Jun 20, 2022
871ef92
Merge branch '1.19' into fluid-flow-api
OroArmor Jun 23, 2022
5f14754
Make the test actually work
OroArmor Jun 23, 2022
ef005b3
Merge branch '1.19' into fluid-flow-api
OroArmor Jul 3, 2022
47a822e
Merge branch '1.19' into fluid-flow-api
OroArmor Aug 6, 2022
9ddf88c
Apply suggestions from code review
OroArmor Aug 6, 2022
a2b52d8
Update library/fluid/fluid_flow/src/main/java/org/quiltmc/qsl/fluid/f…
OroArmor Aug 6, 2022
f205fc5
Merge branch '1.19' into fluid-flow-api
OroArmor Aug 10, 2022
87db399
Merge branch '1.19' into fluid-flow-api
OroArmor Sep 7, 2022
1c4b207
Merge branch '1.19' into fluid-flow-api
OroArmor Oct 18, 2022
6f284b0
Merge branch '1.19' into fluid-flow-api
OroArmor Dec 17, 2022
b793511
Merge remote-tracking branch 'quilt/1.20' into fluid-flow-api
OroArmor Jun 6, 2023
a9b0480
Update to 1.20
OroArmor Jun 6, 2023
82c940c
Merge branch '1.20' into fluid-flow-api
EnnuiL Jun 9, 2023
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
7 changes: 7 additions & 0 deletions library/fluid/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
plugins {
id("qsl.library")
}

qslLibrary {
libraryName = "fluid"
}
15 changes: 15 additions & 0 deletions library/fluid/fluid_flow/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
plugins {
id("qsl.module")
}

qslModule {
name = "Quilt Fluid Flow Event API"
moduleName = "fluid_flow"
id = "quilt_fluid_flow"
description = "Adds events for when fluids flow around other blocks."
moduleDependencies {
core {
api("qsl_base")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2022 QuiltMC
*
* 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 org.quiltmc.qsl.fluid.flow.api;

import java.util.Map;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.Nullable;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;

import org.quiltmc.qsl.base.api.event.Event;

public final class FluidFlowEvents {
private FluidFlowEvents() {}

// Flowing Block to Interacting Block to Event
private static final Map<Block, Map<Block, Event<FluidFlowInteractionCallback>>> EVENT_MAP = new Object2ObjectOpenHashMap<>();

/**
* Registers a new event on a fluid flow.
*
* @param flowingBlock the fluid block that flowed
* @param interactionBlock the block in one of the {@code interactionDirections}
* @param interactionEvent the event to run when the conditions are met
*/
public static void register(Block flowingBlock, Block interactionBlock, FluidFlowInteractionCallback interactionEvent) {
var flowBlockEvents = EVENT_MAP.computeIfAbsent(flowingBlock, flowing -> new Object2ObjectOpenHashMap<>());
flowBlockEvents.computeIfAbsent(interactionBlock, (block) -> Event.create(FluidFlowInteractionCallback.class, fluidFlowInteractionEvents -> (flowingBlockState, interactingBlockState, interactionDirection, flowPos, world) -> {
for (FluidFlowInteractionCallback event : fluidFlowInteractionEvents) {
if (!event.onFlow(flowingBlockState, interactingBlockState, interactionDirection, flowPos, world)) {
return false;
}
}

return true;
})).register(interactionEvent);
}

/**
* Gets the event from the following blocks and direction.
*
* @param flowingBlock the fluid block that flowed
* @param interactionBlock the block it interacts with
* @return an event if the conditions are met, otherwise {@code null}
*/
public static @Nullable Event<FluidFlowInteractionCallback> getEvent(Block flowingBlock, Block interactionBlock) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a standardization on whether @Nullable goes here or on the whole method declaration?

var flowBlockEvents = EVENT_MAP.get(flowingBlock);
if (flowBlockEvents != null) {
return flowBlockEvents.get(interactionBlock);
}

return null;
}

public interface FluidFlowInteractionCallback {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public interface FluidFlowInteractionCallback {
@FunctionalInterface
public interface FluidFlowInteractionCallback {

/**
* An event run when a fluid flows next to a block.
*
* @param flowingBlockState The block state of the fluid block.
* @param interactingBlockState The block state of the interacting block.
* @param interactionDirection The direction from the flowingBlockState to the interactingBlockState.
* @param flowPos The position in the world that the fluid flowed into.
* @param world The world the event took place in.
* @return {@code false} if the event successfully ran, and {@code true} if it was unsuccessful or did not run.
OroArmor marked this conversation as resolved.
Show resolved Hide resolved
*/
boolean onFlow(BlockState flowingBlockState, BlockState interactingBlockState, Direction interactionDirection, BlockPos flowPos, World world);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2022 QuiltMC
*
* 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 org.quiltmc.qsl.fluid.flow.mixin;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;

import org.quiltmc.qsl.fluid.flow.api.FluidFlowEvents;

@Mixin(FluidBlock.class)
public class FluidBlockMixin extends Block {
private static final Direction[] DIRECTIONS = Direction.values();

public FluidBlockMixin(Settings settings) {
super(settings);
}

@Inject(method = "receiveNeighborFluids", at = @At("HEAD"), cancellable = true)
private void receiveNeighborFluids(World world, BlockPos pos, BlockState state, CallbackInfoReturnable<Boolean> cir) {
for (Direction direction : DIRECTIONS) {
var event = FluidFlowEvents.getEvent(this, world.getBlockState(pos.offset(direction)).getBlock());

if (event != null) {
if (!event.invoker().onFlow(state, world.getBlockState(pos.offset(direction)), direction, pos, world)) {
cir.setReturnValue(false);
return;
}
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"required": true,
"package": "org.quiltmc.qsl.fluid.flow.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"FluidBlockMixin"
],
"injectors": {
"defaultRequire": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2022 QuiltMC
*
* 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 org.quiltmc.qsl.fluid.flow;

import net.minecraft.block.Blocks;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.Direction;

import org.quiltmc.loader.api.ModContainer;
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;
import org.quiltmc.qsl.fluid.flow.api.FluidFlowEvents;

public class FluidFlowEventTests implements ModInitializer {
@Override
public void onInitialize(ModContainer container) {
FluidFlowEvents.register(Blocks.WATER, Blocks.BLUE_ICE, (flowingBlockState, interactingBlockState, interactionDirection, flowPos, world) -> {
if (interactionDirection == Direction.DOWN) {
world.setBlockState(flowPos, Blocks.ICE.getDefaultState());
world.playSound(null, flowPos, SoundEvents.BLOCK_GLASS_PLACE, SoundCategory.BLOCKS, 1, 1);
return false;
}

return true;
});
}
}
19 changes: 19 additions & 0 deletions library/fluid/fluid_flow/src/testmod/resources/quilt.mod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"schema_version": 1,
"quilt_loader": {
"group": "org.quiltmc.qsl",
"id": "quilt_fluid_flow_testmod",
"version": "1.0.0",
"metadata": {
"name": "Quilt Flow Flow Event Test Mod",
"license": "Apache-2.0"
},
"intermediate_mappings": "net.fabricmc:intermediary",
"load_type": "always",
"entrypoints": {
"init": [
"org.quiltmc.qsl.fluid.flow.FluidFlowEventTests"
]
}
}
}
23 changes: 23 additions & 0 deletions library/fluid/src/testmod/resources/quilt.mod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"schema_version": 1,
"quilt_loader": {
"group": "org.quiltmc.qsl",
"id": "quilt_fluid_testmod",
"version": "1.0.0",
"metadata": {
"name": "Quilt Fluid Library Test Mod",
"license": "Apache-2.0"
},
"intermediate_mappings": "net.fabricmc:intermediary",
"load_type": "always",
"entrypoints": {
"init": [
"org.quiltmc.qsl.fluid.flow.FluidFlowEventTests"
]
},
"depends": [
"quilt_loader",
"quilt_fluid_flow"
]
}
}
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ library("core")
library("block")
library("data")
library("entity")
library("fluid")
library("rendering")
library("gui")
library("item")
Expand Down