From 3b82842e3d3deb266b95f5d7a75ebb56fc2c7c0c Mon Sep 17 00:00:00 2001 From: Vincent Lee Date: Fri, 3 Dec 2021 07:34:17 -0600 Subject: [PATCH] Add ability for minecarts to specify their detector rail comparator value (#1321) * Add ability for minecarts to specify their detector rail comparator value Address comments * Apply suggestions from code review Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Warn instead of debug Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> --- .../v1/entity/MinecartComparatorLogic.java | 39 ++++++++++++ .../MinecartComparatorLogicRegistry.java | 63 +++++++++++++++++++ .../builder/DetectorRailBlockMixin.java | 57 +++++++++++++++++ .../fabric-object-builder-v1.mixins.json | 1 + 4 files changed, 160 insertions(+) create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogic.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogicRegistry.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/DetectorRailBlockMixin.java diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogic.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogic.java new file mode 100644 index 000000000..c98de10d4 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogic.java @@ -0,0 +1,39 @@ +/* + * 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.object.builder.v1.entity; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.vehicle.AbstractMinecartEntity; +import net.minecraft.util.math.BlockPos; + +/** + * Provides custom comparator output for minecarts resting on detector rails. + * @param the handled minecart type + */ +@FunctionalInterface +public interface MinecartComparatorLogic { + /** + * Compute the comparator output of a detector rail when a minecart is resting + * on top of it. Called from {@link net.minecraft.block.DetectorRailBlock#getComparatorOutput}. + * @param minecart The minecart on the rail + * @param state Block state of the rail + * @param pos Position of the rail + * @return A redstone power value {@literal >=} 0 to use, else a value {@literal <} 0 to try the next minecart with + * a registered logic. If no logic chooses to provide a value, vanilla's logic is invoked. + */ + int getComparatorValue(T minecart, BlockState state, BlockPos pos); +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogicRegistry.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogicRegistry.java new file mode 100644 index 000000000..118123321 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/MinecartComparatorLogicRegistry.java @@ -0,0 +1,63 @@ +/* + * 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.object.builder.v1.entity; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.vehicle.AbstractMinecartEntity; +import net.minecraft.util.registry.Registry; + +/** + * A registry for {@linkplain MinecartComparatorLogic custom minecart compator logic}. + */ +public final class MinecartComparatorLogicRegistry { + private static final Logger LOGGER = LogManager.getLogger(); + private static final Map, MinecartComparatorLogic> logics = new HashMap<>(); + + /** + * Gets the registered custom comparator logic for the specified minecart entity type. + * + * @param type the entity type + * @return the comparator logic, or {@code null} if not registered + */ + @Nullable + @SuppressWarnings("unchecked") + public static MinecartComparatorLogic getCustomComparatorLogic(EntityType type) { + return (MinecartComparatorLogic) logics.get(type); + } + + /** + * Registers a comparator logic for a minecart entity type. + * + *

Registering a second value for an entity type will replace the old logic. + * + * @param the handled minecart type + * @param type the minecart entity type + * @param logic the logic to register + */ + public static void register(EntityType type, MinecartComparatorLogic logic) { + if (logics.put(type, logic) != null) { + LOGGER.warn("Overriding existing minecart comparator logic for entity type {}", Registry.ENTITY_TYPE.getId(type)); + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/DetectorRailBlockMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/DetectorRailBlockMixin.java new file mode 100644 index 000000000..d3bfd5ade --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/DetectorRailBlockMixin.java @@ -0,0 +1,57 @@ +/* + * 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.mixin.object.builder; + +import java.util.List; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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.BlockState; +import net.minecraft.block.DetectorRailBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.vehicle.AbstractMinecartEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.fabricmc.fabric.api.object.builder.v1.entity.MinecartComparatorLogicRegistry; + +@Mixin(DetectorRailBlock.class) +public abstract class DetectorRailBlockMixin { + @Shadow protected abstract List getCarts(World world, BlockPos pos, Class entityClass, @Nullable Predicate entityPredicate); + + @Inject(at = @At("HEAD"), method = "getComparatorOutput", cancellable = true) + private void getCustomComparatorOutput(BlockState state, World world, BlockPos pos, CallbackInfoReturnable cir) { + if (state.get(DetectorRailBlock.POWERED)) { + List carts = getCarts(world, pos, AbstractMinecartEntity.class, + cart -> MinecartComparatorLogicRegistry.getCustomComparatorLogic(cart.getType()) != null); + for (AbstractMinecartEntity cart : carts) { + int comparatorValue = MinecartComparatorLogicRegistry.getCustomComparatorLogic(cart.getType()) + .getComparatorValue(cart, state, pos); + if (comparatorValue >= 0) { + cir.setReturnValue(comparatorValue); + break; + } + } + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json b/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json index 265a90d10..25f89f21c 100644 --- a/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json +++ b/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json @@ -9,6 +9,7 @@ "CriteriaAccessor", "DefaultAttributeRegistryAccessor", "DefaultAttributeRegistryMixin", + "DetectorRailBlockMixin", "MaterialBuilderAccessor", "MixinBlock", "PointOfInterestTypeAccessor",