From d37b37964b486802a4ff4f65ab35ad1cedca4562 Mon Sep 17 00:00:00 2001 From: agnor99 <36055315+justliliandev@users.noreply.github.com> Date: Sun, 6 Oct 2024 18:31:50 +0200 Subject: [PATCH] Add api to add custom conductors to trains --- .../java/com/simibubi/create/AllBlocks.java | 7 ++- .../train/TrainConductorHandler.java | 54 +++++++++++++++++++ ...edTrainConductorInteractionBehaviour.java} | 28 ++++++++-- .../trains/entity/CarriageContraption.java | 27 +++++----- .../entity/CarriageContraptionEntity.java | 4 +- 5 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java rename src/main/java/com/simibubi/create/content/processing/burner/{BlazeBurnerInteractionBehaviour.java => BlockBasedTrainConductorInteractionBehaviour.java} (75%) diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index afe741ca1..bc794ecc3 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -3,6 +3,9 @@ package com.simibubi.create; import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour; import static com.simibubi.create.AllMovementBehaviours.movementBehaviour; import static com.simibubi.create.Create.REGISTRATE; + +import com.simibubi.create.api.contraption.train.TrainConductorHandler; + import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviour; import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock; import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll; @@ -185,7 +188,7 @@ import com.simibubi.create.content.processing.basin.BasinGenerator; import com.simibubi.create.content.processing.basin.BasinMovementBehaviour; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlockItem; -import com.simibubi.create.content.processing.burner.BlazeBurnerInteractionBehaviour; +import com.simibubi.create.content.processing.burner.BlockBasedTrainConductorInteractionBehaviour; import com.simibubi.create.content.processing.burner.BlazeBurnerMovementBehaviour; import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock; import com.simibubi.create.content.redstone.RoseQuartzLampBlock; @@ -708,7 +711,7 @@ public class AllBlocks { .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour())) - .onRegister(interactionBehaviour(new BlazeBurnerInteractionBehaviour())) + .onRegister(block -> TrainConductorHandler.registerBlazeBurner()) .item(BlazeBurnerBlockItem::withBlaze) .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) .build() diff --git a/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java b/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java new file mode 100644 index 000000000..05cd1e09e --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java @@ -0,0 +1,54 @@ +package com.simibubi.create.api.contraption.train; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllInteractionBehaviours; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; + +import com.simibubi.create.content.processing.burner.BlockBasedTrainConductorInteractionBehaviour; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; + + +import org.jetbrains.annotations.ApiStatus; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; + + +/** + * All required methods to make your block a train conductor similar to the blaze burner + */ +public interface TrainConductorHandler { + + @ApiStatus.Internal + List CONDUCTOR_HANDLERS = new ArrayList<>(); + + + + boolean isValidConductor(BlockState state); + + private static void registerHandler(TrainConductorHandler handler) { + CONDUCTOR_HANDLERS.add(handler); + } + + static void registerConductor(ResourceLocation blockRl, Predicate isValidConductor, UpdateScheduleCallback updateScheduleCallback) { + AllInteractionBehaviours.registerBehaviour(blockRl, new BlockBasedTrainConductorInteractionBehaviour(isValidConductor, updateScheduleCallback)); + registerHandler(isValidConductor::test); + } + + @ApiStatus.Internal + static void registerBlazeBurner() { + registerConductor(AllBlocks.BLAZE_BURNER.getId(), blockState -> AllBlocks.BLAZE_BURNER.has(blockState) + && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.NONE, UpdateScheduleCallback.EMPTY); + } + + interface UpdateScheduleCallback { + + UpdateScheduleCallback EMPTY = (hasSchedule, blockState, blockStateSetter) -> {}; + + void update(boolean hasSchedule, BlockState currentBlockState, Consumer blockStateSetter); + } +} diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/processing/burner/BlockBasedTrainConductorInteractionBehaviour.java similarity index 75% rename from src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerInteractionBehaviour.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlockBasedTrainConductorInteractionBehaviour.java index 0473f856d..4bde1367f 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlockBasedTrainConductorInteractionBehaviour.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.processing.burner; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.contraption.train.TrainConductorHandler; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; -import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.Train; @@ -21,9 +21,21 @@ import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour { +import java.util.function.Predicate; + +public class BlockBasedTrainConductorInteractionBehaviour extends MovingInteractionBehaviour { + + private final Predicate isValidConductor; + private final TrainConductorHandler.UpdateScheduleCallback callback; + + public BlockBasedTrainConductorInteractionBehaviour(Predicate isValidConductor, TrainConductorHandler.UpdateScheduleCallback callback) { + this.isValidConductor = isValidConductor; + this.callback = callback; + } @Override public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, @@ -40,8 +52,7 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour StructureBlockInfo info = carriageContraption.getBlocks() .get(localPos); - if (info == null || !info.state().hasProperty(BlazeBurnerBlock.HEAT_LEVEL) - || info.state().getValue(BlazeBurnerBlock.HEAT_LEVEL) == HeatLevel.NONE) + if (info == null || !isValidConductor.test(info.state())) return false; Direction assemblyDirection = carriageContraption.getAssemblyDirection(); @@ -74,6 +85,7 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"), true); player.setItemInHand(activeHand, train.runtime.returnSchedule()); + callback.update(false, info.state(), newBlockState -> setBlockState(localPos, contraptionEntity, newBlockState)); return true; } @@ -89,7 +101,7 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour player.displayClientMessage(Lang.translateDirect("schedule.no_stops"), true); return true; } - + callback.update(true, info.state(), newBlockState -> setBlockState(localPos, contraptionEntity, newBlockState)); train.runtime.setSchedule(schedule, false); AllAdvancements.CONDUCTOR.awardTo(player); AllSoundEvents.CONFIRM.playOnServer(player.level(), player.blockPosition(), 1, 1); @@ -105,4 +117,10 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour return true; } + private void setBlockState(BlockPos localPos, AbstractContraptionEntity contraption, BlockState newState) { + StructureTemplate.StructureBlockInfo info = contraption.getContraption().getBlocks().get(localPos); + if (info != null) { + setContraptionBlockData(contraption, localPos, new StructureTemplate.StructureBlockInfo(info.pos(), newState, info.nbt())); + } + } } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java index 5a6f1b47b..ab566a6f8 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java @@ -7,6 +7,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import com.simibubi.create.api.contraption.train.TrainConductorHandler; + import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; @@ -17,8 +19,6 @@ import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.contraptions.MountedStorageManager; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; import com.simibubi.create.content.contraptions.minecart.TrainCargoManager; -import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -51,7 +51,7 @@ public class CarriageContraption extends Contraption { private boolean forwardControls; private boolean backwardControls; - public Couple blazeBurnerConductors; + public Couple blockConductors; public Map> conductorSeats; public ArrivalSoundQueue soundQueue; @@ -61,7 +61,7 @@ public class CarriageContraption extends Contraption { private int bogeys; private boolean sidewaysControls; private BlockPos secondBogeyPos; - private List assembledBlazeBurners; + private List assembledBlockConductors; // render public int portalCutoffMin; @@ -72,8 +72,8 @@ public class CarriageContraption extends Contraption { public CarriageContraption() { conductorSeats = new HashMap<>(); - assembledBlazeBurners = new ArrayList<>(); - blazeBurnerConductors = Couple.create(false, false); + assembledBlockConductors = new ArrayList<>(); + blockConductors = Couple.create(false, false); soundQueue = new ArrivalSoundQueue(); portalCutoffMin = Integer.MIN_VALUE; portalCutoffMax = Integer.MAX_VALUE; @@ -103,10 +103,10 @@ public class CarriageContraption extends Contraption { if (sidewaysControls) throw new AssemblyException(Lang.translateDirect("train_assembly.sideways_controls")); - for (BlockPos blazePos : assembledBlazeBurners) + for (BlockPos blazePos : assembledBlockConductors) for (Direction direction : Iterate.directionsInAxis(assemblyDirection.getAxis())) if (inControl(blazePos, direction)) - blazeBurnerConductors.set(direction != assemblyDirection, true); + blockConductors.set(direction != assemblyDirection, true); for (BlockPos seatPos : getSeats()) for (Direction direction : Iterate.directionsInAxis(assemblyDirection.getAxis())) if (inControl(seatPos, direction)) @@ -166,9 +166,8 @@ public class CarriageContraption extends Contraption { captureBE ? world.getBlockEntity(pos) : null); } - if (AllBlocks.BLAZE_BURNER.has(blockState) - && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != HeatLevel.NONE) - assembledBlazeBurners.add(toLocalPos(pos)); + if (TrainConductorHandler.CONDUCTOR_HANDLERS.stream().anyMatch(handler -> handler.isValidConductor(blockState))) + assembledBlockConductors.add(toLocalPos(pos)); if (AllBlocks.TRAIN_CONTROLS.has(blockState)) { Direction facing = blockState.getValue(ControlsBlock.FACING); @@ -192,8 +191,8 @@ public class CarriageContraption extends Contraption { NBTHelper.writeEnum(tag, "AssemblyDirection", getAssemblyDirection()); tag.putBoolean("FrontControls", forwardControls); tag.putBoolean("BackControls", backwardControls); - tag.putBoolean("FrontBlazeConductor", blazeBurnerConductors.getFirst()); - tag.putBoolean("BackBlazeConductor", blazeBurnerConductors.getSecond()); + tag.putBoolean("FrontBlazeConductor", blockConductors.getFirst()); + tag.putBoolean("BackBlazeConductor", blockConductors.getSecond()); ListTag list = NBTHelper.writeCompoundList(conductorSeats.entrySet(), e -> { CompoundTag compoundTag = new CompoundTag(); compoundTag.put("Pos", NbtUtils.writeBlockPos(e.getKey())); @@ -213,7 +212,7 @@ public class CarriageContraption extends Contraption { assemblyDirection = NBTHelper.readEnum(nbt, "AssemblyDirection", Direction.class); forwardControls = nbt.getBoolean("FrontControls"); backwardControls = nbt.getBoolean("BackControls"); - blazeBurnerConductors = + blockConductors = Couple.create(nbt.getBoolean("FrontBlazeConductor"), nbt.getBoolean("BackBlazeConductor")); conductorSeats.clear(); NBTHelper.iterateCompoundList(nbt.getList("ConductorSeats", Tag.TAG_COMPOUND), diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java index abfd3a669..1396ea820 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java @@ -492,8 +492,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (!(contraption instanceof CarriageContraption cc)) return sides; - sides.setFirst(cc.blazeBurnerConductors.getFirst()); - sides.setSecond(cc.blazeBurnerConductors.getSecond()); + sides.setFirst(cc.blockConductors.getFirst()); + sides.setSecond(cc.blockConductors.getSecond()); for (Entity entity : getPassengers()) { if (entity instanceof Player)