diff --git a/docs/content/Development/External-Resources.md b/docs/content/Development/External-Resources.md index 46907c07632..208d15c04f0 100644 --- a/docs/content/Development/External-Resources.md +++ b/docs/content/Development/External-Resources.md @@ -21,14 +21,6 @@ as other resources you might find helpful. - [MCJty's Modding Wiki](https://www.mcjty.eu/docs/intro) -## LDLib - -LDLib is the main library we're using for GTCEu-Modern. - -!!! link "LDLib Docs" - [:material-github: LDLib-Architectury :material-arrow-right: Wiki](https://github.com/Low-Drag-MC/LDLib-Architectury/wiki) - - ## Mixins !!! link "Overview on using Mixins" diff --git a/docs/content/Development/General-Topics/Energy-Fluid-Item-Storage.md b/docs/content/Development/General-Topics/Energy-Fluid-Item-Storage.md index b478d3a3f19..e870f1ef51a 100644 --- a/docs/content/Development/General-Topics/Energy-Fluid-Item-Storage.md +++ b/docs/content/Development/General-Topics/Energy-Fluid-Item-Storage.md @@ -7,8 +7,7 @@ title: Item/Fluid/Energy Storage !!! note - In general, these containers should be created as `final` fields (that's what we need for the - [SyncData](../SyncData/index.md) system). + In general, these containers should be created as `final` fields. Set their base arguments in the constructor (you can pass args for subclasses to modify). @@ -47,7 +46,6 @@ To do so, use either of the following interfaces: - `IFluidTransfer` - `IEnergyContainer` - ## Specialized proxy implementations In case you have special requirements to your containers, you may be able to use one of these implementations in @@ -61,67 +59,9 @@ They generally act as a proxy to the underlying container(s), while also handlin - `FluidTransferList` - `EnergyContainerList` - ### IO-specific container proxies For proxying multiple containers, limited to a specific IO direction. - `IOItemTransferList` - `IOFluidTransferList` - - -### Rate-Limited proxies - -!!! warning inline end "Not merged yet
_Branch: `mi-ender-link`_" - -If you need to proxy any item or fluid container that needs to be rate limited for insertion and extraction, you can -use either of the following classes: - -- `LimitingItemTransferProxy` -- `LimitingFluidTransferProxy` - -The transfer limit passed as a constructor parameter will not renew automatically. Your container will therefore stop -transferring anything once this limit is reached. - -If you want to make this a rate limit instead, you will have to schedule a task that regularly resets the transfer -limit to the maximum value for your task's interval: - -??? example "Example Usage" - - ```java - public class MyCover extends CoverBehavior { - private LimitingFluidTransferProxy transferProxy; - private ConditionalSubscriptionHandler rateLimitSubscription; - - public MyCover(IFluidTransfer myFluidTransfer) { - super(/* ... */); - - transferProxy = new LimitingFluidTransferProxy( - myFluidTransfer, - 0L // Initial limit of 0, will be updated regularly in isRateLimitRefreshActive() - ); - rateLimitSubscription = new ConditionalSubscriptionHandler( - this, - this::resetTransferRateLimit, - this::isRateLimitRefreshActive - ); - } - - @Override - public void onLoad() { - super.onLoad(); - rateLimitSubscription.initialize(coverHolder.getLevel()); - } - - private void resetTransferRateLimit() { - if (transferProxy == null) - return; - - transferProxy.setRemainingTransfer(transferRate.getMilliBuckets() * 20); - } - - private boolean isRateLimitRefreshActive() { - // ... - } - } - ``` \ No newline at end of file diff --git a/docs/content/Development/General-Topics/Global-Data.md b/docs/content/Development/General-Topics/Global-Data.md index 0d40830191f..a8793d29465 100644 --- a/docs/content/Development/General-Topics/Global-Data.md +++ b/docs/content/Development/General-Topics/Global-Data.md @@ -9,33 +9,3 @@ In certain cases (e.g. in a cache that holds all currently loaded instances of a in a global (static and mutable) variable. When doing so, you need to ensure that remote and serverside instances don't get mixed up. - - -## Using `SideLocal` - -!!! warning inline end "Not yet merged
_Branch: `mi-ender-link`_" - -To make working with this requirement easier, You can use `SideLocal` to store your global data. -It is similar to Java's `ThreadLocal`, but operates on the game's sides instead. - -If you are currently on the remote side (`GTCEuAPI.isClientThread()` / on the client's `main` thread), it will return the -remote side's instance of your data. Otherwise, you will get the server side's instance. - -??? example "Example Usage" - - ```java - public class MyCache { - private static SideLocal> cache = new SideLocal<>(HashMap::new); - - public static void cacheData(UUID id, MyData data) { - cache.get().put(id, data); - } - - public static MyData getData(UUID id) { - return cache.get().get(id); - } - } - ``` - - Alternatively to passing an initializer for both instances to `SideLocal`'s constructor, you can also supply - separate instances for the remote and server side. \ No newline at end of file diff --git a/docs/content/Development/General-Topics/Machine-Trait-System.md b/docs/content/Development/General-Topics/Machine-Trait-System.md new file mode 100644 index 00000000000..fd92ff70963 --- /dev/null +++ b/docs/content/Development/General-Topics/Machine-Trait-System.md @@ -0,0 +1,107 @@ +--- +title: Machine Trait System +--- + +# Machine Trait System + +The machine trait system allows for attaching extra capabilities and behaviours to a machine by attaching traits to machine instances. Traits can listen for specific machine events, interactions, and provide capabilities, allowing for machine functionality to be implemented via a composition-based design. + +## Attaching and using machine traits + +Attaching traits must be done before machine instances are fully initialised, and are typically attached in the constructor. + +### Attaching and using traits: + +Attaching a machine trait to a machine is done with the `MetaMachine::attachTrait` and `MetaMachine::attachPersistentTrait` methods. + +When attaching traits, a `callbackPriority` value can be given. Traits with a higher priority will have their events and interactions called +first, which may prevent traits with a lower priority from handling some events. + +!!! warning + Traits must be attached to a machine instance via either `attachTrait` or `attachPersistentTrait`. + If a trait is created without either of these methods being called, the trait will not be valid. + +```java +public class CustomMachine extends MetaMachine { + + @SaveField + protected final NotifiableFluidTank tank; + + public CustomMachine(BlockEntityCreationInfo info, int capacity) { + super(info); + + // Because the tank field is annotated with `@SaveField`, the fluid tank will be saved into the machines data. + this.tank = attachTrait(new NotifiableFluidTank(1, capacity, IO.BOTH)); + + // Registers an auto output trait that provides fluid output behaviour for the given fluid tank. + // Instead of using an annotated field to save traits, they can also be registered to be saved. + // The trait save name should remain the same, otherwise the trait save data won't be loaded. + AutoOutputTrait autoOutput = attachPersistentTrait("autoOutput", AutoOutputTrait.ofFluids(tank)); + + autoOutput.setFluidOutputDirection(Direction.DOWN); + autoOutput.setFluidOutputDirectionValidator(d -> d == Direction.DOWN); + } + + public void usingTraits() { + MetaMachine machine = getMachine(); + + // Most trait objects have a `TYPE` static field, it can be used to get traits with a specific type. + AutoOutputTrait autoOutputTrait = machine.getTrait(AutoOutputTrait.TYPE); + Optional recipeLogicOptional = machine.getTrait(RecipeLogic.TYPE); + + // Gets all traits with the specified type. + List allItemStackHandlers = machine.getTraits(NotifiableItemStackHandler.TYPE); + + List allTraits = machine.getAllTraits(); + } +} +``` + +### Creating custom traits + +Custom machine traits are created by extending `MachineTrait` or `MultiblockMachineTrait` + +Machine traits have access to a number of machine events and callbacks, but some extra behaviours can be added by having a trait implement a trait feature interface. For example, `IInteractionTrait` to add custom interaction behaviour. The full list of trait features is in `api/machine/trait/feature`. + +```java +public class CustomMachineTrait extends MachineTrait implements IInteractionTrait { + + // Machine traits should have a type object defined, unless a parent class of this machine trait already defines a type + public static final MachineTraitType TYPE = new MachineTraitType<>(CustomMachineTrait.class); + + public CustomMachineTrait() { + + } + + // Machine traits must also define a getter for the trait type + @Override + public MachineTraitType getType() { + return TYPE; + } + + // A list of classes or interfaces which a machine must be in order for this trait to be attached. + // A machine trait must be at least one of these interfaces/classes. + // By default, traits can be attached to any machine. + @Override + protected List> validMachineClasses() { + return List.of(CustomMachine.class); + } + + // An example of a machine trait event callback. + // Traits with a higher trait priority will have their events called first, + // which may block lower priority traits from receiving events. + // All traits default to a priority of 1. + @Override + public Pair<@Nullable GTToolType, InteractionResult> onToolClick(ExtendedUseOnContext context) { + var toolType = context.getToolType(); + if (toolType.contains(GTToolType.WRENCH)) { + return Pair.of(GTToolType.WRENCH, onWrenchClick(context)); + } + return IInteractionTrait.super.onToolClick(context); + } + + private InteractionResult onWrenchClick(ExtendedUseOnContext context) { + return InteractionResult.PASS; + } +} +``` \ No newline at end of file diff --git a/docs/content/Development/index.md b/docs/content/Development/index.md index 796b0d5f656..6b81b32039e 100644 --- a/docs/content/Development/index.md +++ b/docs/content/Development/index.md @@ -10,12 +10,6 @@ pull request with your changes. The following pages describe a few important concepts that you will likely run into when working with our codebase. -!!! link "LDLib Docs" - [:material-github: LDLib-Architectury :material-arrow-right: Wiki](https://github.com/Low-Drag-MC/LDLib-Architectury/wiki) - - This mod is based on the LDLib library for a lot of comminly used functionalities. - Please refer to its documentation as well. - !!! link "Architectury Gradle Plugin" [Architectury-Wiki :material-arrow-right: Gradle Plugin](https://docs.architectury.dev/plugin/introduction) diff --git a/docs/content/Modpacks/Changes/v8.0.0.md b/docs/content/Modpacks/Changes/v8.0.0.md index b97deff01e5..fc7c33f8651 100644 --- a/docs/content/Modpacks/Changes/v8.0.0.md +++ b/docs/content/Modpacks/Changes/v8.0.0.md @@ -66,6 +66,8 @@ Machine interactions have been split into two methods: `MetaMachine::onUse` and A new system for attaching traits and custom behaviour to machines has been added, and many machine interfaces and traits now use this new system. +See [this page](../../Development/General-Topics/Machine-Trait-System.md) for an overview of the new system. + ### Machine constructor and trait initialisation changes The constructors for a large number of machines have changed in order to simply machine instance creation. Additionally, methods for trait creation have also been removed and now form part of the machine constructor. @@ -90,8 +92,6 @@ The constructors for a large number of machines have changed in order to simply - Removed `createRecipeLogic` method - Constructor now has an optional `Supplier` argument, defaults to the standard `RecipeLogic` class -### New System Example - #### IMPORTANT MIGRATION NOTE: Traits must be attached to a machine directly by calling `attachTrait(MachineTrait trait)` on the trait being attached. @@ -105,44 +105,6 @@ this.itemHandler = attachTrait(new NotifiableItemStackHandler(0, IO.BOTH)) ``` When migrating, remove the `this` argument from the machine trait constructor and instead attach the trait. -Example of the new `AutoOutputTrait` - -```java -public class CustomDrumMachine extends MetaMachine { - - protected final NotifiableFluidTank tank; - public final AutoOutputTrait autoOutput; - - public DrumMachine(BlockEntityCreationInfo info, int capacity) { - super(info); - - // Traits must be attached in the constructor. - - this.tank = attachTrait(new NotifiableFluidTank(1, capacity, IO.BOTH)); - - // Registers an auto output trait that provides fluid output behaviour for the given fluid tank. - this.autoOutput = attachTrait(AutoOutputTrait.ofFluids(tank)); - - autoOutput.setFluidOutputDirection(Direction.DOWN); - autoOutput.setFluidOutputDirectionValidator(d -> d == Direction.DOWN); - } - - // Any code can query traits from a machine - public static void queryTraits(MetaMachine machine) { - - // Returns a trait with the given type, or null. - AutoOutputTrait autoOutputTrait = machine.getTraitHolder().getTrait(AutoOutputTrait.TYPE); - - Optional recipeLogicOptional = machine.getTraitHolder().getTrait(RecipeLogic.TYPE); - - // Gets all traits with the specified type. - List allItemStackHandlers = machine.getTraitHolder().getTraits(NotifiableItemStackHandler.TYPE); - - } -} -``` - - ### Removed interfaces A large number of machine feature interfaces have been removed, and have had their functionality merged into the standard MetaMachine class, or now use the new machine trait system: diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 23ce21657c2..53efcdcd9bf 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -14,7 +14,6 @@ "behavior.portable_scanner.debug_lag_count": "˙ɹǝʌɹǝS ǝɥʇ uo )sɯ%s uɐɥʇ ɹǝbuoן buıʞɐʇ buıɥʇʎuɐ( sbuıuɹɐM ǝʞıdS bɐꞀ %s pǝsnɐƆ", "behavior.portable_scanner.debug_machine": "%s :ᗡI-ɐʇǝW", "behavior.portable_scanner.debug_machine_invalid": "¡pıןɐʌuı ", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": "¡ןןnu ", "behavior.portable_scanner.debug_machine_valid": "pıןɐʌ ", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "Ɐ %s ʇɐ ∩Ǝ )%s( %s :NI xɐW", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 6eca15057a9..c9d6d18f758 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -14,7 +14,6 @@ "behavior.portable_scanner.debug_lag_count": "Caused %s Lag Spike Warnings (anything taking longer than %sms) on the Server.", "behavior.portable_scanner.debug_machine": "Meta-ID: %s", "behavior.portable_scanner.debug_machine_invalid": " invalid!", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " null!", "behavior.portable_scanner.debug_machine_valid": " valid", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "Max IN: %s (%s) EU at %s A", diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/MaterialBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/MaterialBlock.java index aa4626ea197..13f344e019b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/MaterialBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/MaterialBlock.java @@ -187,8 +187,8 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player blockPos.move(Direction.UP); continue; } - BlockEntity te = level.getBlockEntity(blockPos); - if (te instanceof PipeBlockEntity pbe && !pbe.getFrameMaterial().isNull()) { + BlockEntity be = level.getBlockEntity(blockPos); + if (be instanceof PipeBlockEntity pbe && !pbe.getFrameMaterial().isNull()) { blockPos.move(Direction.UP); continue; } @@ -197,7 +197,7 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player if (!player.isCreative()) stack.shrink(1); return InteractionResult.SUCCESS; - } else if (te instanceof PipeBlockEntity pbe && pbe.getFrameMaterial().isNull()) { + } else if (be instanceof PipeBlockEntity pbe && pbe.getFrameMaterial().isNull()) { pbe.setFrameMaterial(frameBlock.material); if (!player.isCreative()) @@ -223,8 +223,8 @@ public static MaterialBlock getFrameboxFromItem(ItemStack stack) { } public boolean removeFrame(Level level, BlockPos pos, Player player, ItemStack stack) { - BlockEntity te = level.getBlockEntity(pos); - if (te instanceof PipeBlockEntity pipeTile) { + BlockEntity be = level.getBlockEntity(pos); + if (be instanceof PipeBlockEntity pipeTile) { Material mat = pipeTile.getFrameMaterial(); if (!mat.isNull()) { pipeTile.setFrameMaterial(GTMaterials.NULL); diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java index ebaca50dc9b..93c4037f202 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java @@ -17,6 +17,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.locale.Language; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.RandomSource; @@ -119,7 +120,16 @@ public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, @Nullabl if (!pLevel.isClientSide) { var machine = MetaMachine.getMachine(pLevel, pPos); if (machine != null) { - machine.onMachinePlaced(player, pStack); + if (player instanceof ServerPlayer sPlayer) { + machine.setOwnerUUID(sPlayer.getUUID()); + } + + if (machine instanceof IDropSaveMachine dropSaveMachine) { + CompoundTag tag = pStack.getTag(); + if (tag != null) { + dropSaveMachine.loadFromItem(tag); + } + } } } } @@ -325,16 +335,14 @@ public int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos) { return machine.getAnalogOutputSignal(); } - ///////// - @Override - public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, - boolean isMoving) { + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, + boolean movedByPiston) { var machine = MetaMachine.getMachine(level, pos); if (machine != null) { - machine.onNeighborChanged(block, fromPos, isMoving); + machine.onNeighborChanged(neighborBlock, neighborPos, movedByPiston); } - super.neighborChanged(state, level, pos, block, fromPos, isMoving); + super.neighborChanged(state, level, pos, neighborBlock, neighborPos, movedByPiston); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java index 0c81186ff92..d71b2bebf34 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/PipeBlock.java @@ -471,9 +471,9 @@ public BlockState getAppearance(BlockState state, BlockAndTintGetter level, Bloc @Override public List getDrops(BlockState state, LootParams.Builder builder) { var context = builder.withParameter(LootContextParams.BLOCK_STATE, state).create(LootContextParamSets.BLOCK); - BlockEntity tileEntity = context.getParamOrNull(LootContextParams.BLOCK_ENTITY); + BlockEntity blockEntity = context.getParamOrNull(LootContextParams.BLOCK_ENTITY); List drops = new ArrayList<>(super.getDrops(state, builder)); - if (tileEntity instanceof IPipeNode pipeTile) { + if (blockEntity instanceof IPipeNode pipeTile) { if (!pipeTile.getFrameMaterial().isNull()) { drops.addAll(GTMaterialBlocks.MATERIAL_BLOCKS.get(TagPrefix.frameGt, pipeTile.getFrameMaterial()) .getDefaultState().getDrops(builder)); diff --git a/src/main/java/com/gregtechceu/gtceu/api/blockentity/IGregtechBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/api/blockentity/IGregtechBlockEntity.java index 946cb3f5657..866c0cfadde 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/blockentity/IGregtechBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/api/blockentity/IGregtechBlockEntity.java @@ -23,7 +23,14 @@ public interface IGregtechBlockEntity extends ISyncManaged, ITickSubscription, I boolean isRemoved(); - void notifyBlockUpdate(); + /** + * Called to notify neighboring blocks that this block has changed. + */ + default void notifyBlockUpdate() { + if (getLevel() != null) { + getLevel().updateNeighborsAt(getBlockPos(), getLevel().getBlockState(getBlockPos()).getBlock()); + } + } default void scheduleNeighborShapeUpdate() { Level level = getLevel(); diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/ICoverable.java b/src/main/java/com/gregtechceu/gtceu/api/capability/ICoverable.java index 16852d2a582..d06645b7fc5 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/ICoverable.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/ICoverable.java @@ -31,6 +31,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.items.IItemHandlerModifiable; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -108,6 +109,7 @@ default void unsubscribe(@Nullable TickableSubscription current) { * @param coverBehavior * @param side */ + @ApiStatus.Internal void setCoverAtSide(@Nullable CoverBehavior coverBehavior, Direction side); @Nullable diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/compat/EUToFEProvider.java b/src/main/java/com/gregtechceu/gtceu/api/capability/compat/EUToFEProvider.java index b3b025c8f1a..43c4506fba4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/compat/EUToFEProvider.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/compat/EUToFEProvider.java @@ -25,8 +25,8 @@ public class EUToFEProvider extends CapabilityCompatProvider { */ private long feBuffer; - public EUToFEProvider(BlockEntity tileEntity) { - super(tileEntity); + public EUToFEProvider(BlockEntity blockEntity) { + super(blockEntity); } @Override @@ -156,7 +156,7 @@ public long getEnergyStored() { * IEnergyStorage should handle it. * This simulates that behavior in most places by allowing our "is there space" checks to pass and letting the * cable attempt to insert energy. - * If the wrapped TE actually cannot accept any more energy, the energy transfer will return 0 before any + * If the wrapped BE actually cannot accept any more energy, the energy transfer will return 0 before any * changes to our internal rf buffer. */ @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java b/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java index 276b38b7575..24ce428669d 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java @@ -44,8 +44,7 @@ import javax.annotation.ParametersAreNonnullByDefault; /** - * Represents cover instance attached on the specific side of meta tile entity - * Cover filters out interaction and logic of meta tile entity + * Represents a cover instance attached on a specific side of a machine */ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @@ -100,7 +99,7 @@ public boolean canAttach() { } /** - * Will be called on server side after the cover attachment to the meta tile entity + * Will be called on server side after the cover attachment to the machine * Cover can change it's internal state here and return initial data as nbt. * * @param itemStack the item cover was attached from diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/CoverDefinition.java b/src/main/java/com/gregtechceu/gtceu/api/cover/CoverDefinition.java index 5a11aac76b3..4e7a847ddd2 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/CoverDefinition.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/CoverDefinition.java @@ -41,8 +41,8 @@ public CoverDefinition(ResourceLocation id, CoverBehaviourProvider behaviorCreat } } - public CoverBehavior createCoverBehavior(ICoverable metaTileEntity, Direction side) { - return behaviorCreator.create(this, metaTileEntity, side); + public CoverBehavior createCoverBehavior(ICoverable coverable, Direction side) { + return behaviorCreator.create(this, coverable, side); } private static class ClientHelper { diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/PipeBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/PipeBlockItem.java index ebf99a4590a..1679a40cc2d 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/PipeBlockItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/PipeBlockItem.java @@ -78,8 +78,8 @@ public boolean placeBlock(BlockPlaceContext context, BlockState state) { selfTile.setConnection(side.getOpposite(), true, false); } for (Direction facing : GTUtil.DIRECTIONS) { - BlockEntity te = selfTile.getNeighbor(facing); - if (te instanceof IPipeNode otherPipe) { + BlockEntity be = selfTile.getNeighbor(facing); + if (be instanceof IPipeNode otherPipe) { if (otherPipe.isConnected(facing.getOpposite())) { if (otherPipe.getPipeBlock().canPipesConnect(otherPipe, facing.getOpposite(), selfTile)) { selfTile.setConnection(facing, true, true); @@ -88,7 +88,7 @@ public boolean placeBlock(BlockPlaceContext context, BlockState state) { } } } else if (!ConfigHolder.INSTANCE.machines.gt6StylePipesCables && - selfTile.getPipeBlock().canPipeConnectToBlock(selfTile, facing, te)) { + selfTile.getPipeBlock().canPipeConnectToBlock(selfTile, facing, be)) { selfTile.setConnection(facing, true, false); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java b/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java index a79ccf07b39..9621d355051 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java @@ -14,11 +14,32 @@ public interface IToolGridHighlight { + /** + * Called to determine if the grid overlay should be rendered on this machine. + * + * @param player Player looking at this machine + * @param pos Block pos + * @param state Block state + * @param held Item that player is holding + * @param toolTypes The GT tool types of the held item, if any + * @return If the grid overlay should be drawn on the machine. + */ default boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, ItemStack held, Set toolTypes) { return true; } + /** + * Called when the machine grid overlay is being rendered to determine the icon to be rendered within the grid + * segment on a specifc side. + * + * @param player Player looking at this machine + * @param pos Block pos + * @param state Block state + * @param toolTypes The GT tool types of the held item, if any + * @param side The machine side which this grid segment correspond to + * @return The icon to be rendered, or null + */ default @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, Direction side) { return null; diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java index e0ad3dc7703..270aad6f1fb 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java @@ -121,7 +121,7 @@ public boolean canPlaceCoverOnSide(CoverDefinition definition, Direction side) { machine.addCollisionBoundingBox(collisionList); // noinspection RedundantIfStatement if (ICoverable.doesCoverCollide(side, collisionList, getCoverPlateThickness())) { - // cover collision box overlaps with meta tile entity collision box + // cover collision box overlaps with machine collision box return false; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java index b6564371097..7a011bb3c71 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java @@ -20,13 +20,13 @@ import com.gregtechceu.gtceu.api.item.tool.ToolHelper; import com.gregtechceu.gtceu.api.machine.feature.*; import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMaintenanceMachine; -import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiPart; import com.gregtechceu.gtceu.api.machine.property.GTMachineModelProperties; import com.gregtechceu.gtceu.api.machine.trait.MachineTrait; import com.gregtechceu.gtceu.api.machine.trait.MachineTraitHolder; import com.gregtechceu.gtceu.api.machine.trait.MachineTraitType; import com.gregtechceu.gtceu.api.machine.trait.feature.IFrontFacingTrait; import com.gregtechceu.gtceu.api.machine.trait.feature.IInteractionTrait; +import com.gregtechceu.gtceu.api.machine.trait.feature.IRedstoneSignalTrait; import com.gregtechceu.gtceu.api.machine.trait.feature.IRenderingTrait; import com.gregtechceu.gtceu.api.misc.*; import com.gregtechceu.gtceu.api.pattern.util.RelativeDirection; @@ -65,7 +65,6 @@ import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; @@ -81,6 +80,7 @@ import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.extensions.IForgeBlock; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; @@ -98,6 +98,9 @@ import java.util.function.Consumer; import java.util.function.Predicate; +/** + * The base BlockEntity for all GT machines. + */ public class MetaMachine extends ManagedSyncBlockEntity implements IGregtechBlockEntity, IToolGridHighlight, IFancyTooltip, IPaintable, IMachineFeature, ICopyable { @@ -154,6 +157,11 @@ public void load(CompoundTag tag) { super.load(tag); } + /** + * Called when this machine is loaded. The entire world is not loaded when this method is called. + * To schedule code to run on the first full world tick, do + * {@code serverLevel.getServer().tell(new TickTask(0, CALLBACK))} + */ @MustBeInvokedByOverriders public void onLoad() { getAllTraits().forEach(MachineTrait::onMachineLoad); @@ -172,6 +180,9 @@ public final void setRemoved() { onUnload(); } + /** + * Called when this machine is about to be unloaded. + */ @MustBeInvokedByOverriders public void onUnload() { getAllTraits().forEach(MachineTrait::onMachineUnload); @@ -182,23 +193,18 @@ public void onUnload() { serverTicks.clear(); } - public void onMachinePlaced(@Nullable LivingEntity player, ItemStack stack) { - if (player instanceof ServerPlayer sPlayer) { - ownerUUID = sPlayer.getUUID(); - } - - if (this instanceof IDropSaveMachine dropSaveMachine) { - CompoundTag tag = stack.getTag(); - if (tag != null) { - dropSaveMachine.loadFromItem(tag); - } - } - } - + /** + * Called when this machine is destroyed. + */ public void onMachineDestroyed() { getAllTraits().forEach(MachineTrait::onMachineDestroyed); } + /** + * Called to modify the drops returned when this block is destroyed + * + * @param drops A modifiable list of drops. + */ public void modifyDrops(List drops) {} ////////////////////////////////////// @@ -229,12 +235,16 @@ public void unsubscribe(@Nullable TickableSubscription current) { } } + @ApiStatus.Internal public final void serverTick() { executeTick(); } public boolean isFirstDummyWorldTick = true; + /** + * Called every tick on the client side. + */ @OnlyIn(Dist.CLIENT) public void clientTick() { if (getLevel() instanceof DummyWorld) { @@ -305,9 +315,26 @@ public T attachTrait(T trait, int callbackPriority) { * @param traitName Unique identifier for this trait. * @param trait The trait to register */ - public void attachPersistentTrait(String traitName, MachineTrait trait) { + public T attachPersistentTrait(String traitName, T trait) { traitHolder.attachTrait(trait); traitHolder.registerPersistentTrait(traitName, trait); + return trait; + } + + /** + * Registers a trait with data to be saved or synced to the client. + * Do not register a persistent trait and also store that trait as a syncable machine field, otherwise the trait + * data will be duplicated. Use only one sync method. + * + * @param traitName Unique identifier for this trait. + * @param callbackPriority The trait's callback priority. Traits with a higher priority will have their events fired + * first, which may prevent traits with a lower priority from handling some events. + * @param trait The trait to register + */ + public T attachPersistentTrait(String traitName, T trait, int callbackPriority) { + traitHolder.attachTrait(trait, callbackPriority); + traitHolder.registerPersistentTrait(traitName, trait); + return trait; } /** @@ -354,10 +381,14 @@ public Optional getTraitOptional(MachineTraitType ////////////////////////////////////// /** - * Called when a player clicks this machine with a tool - * - * @return SUCCESS / CONSUME (will damage tool) / FAIL if something happened, so tools will get damaged and - * animations will be played + * Called when a player clicks this machine with a GT tool + * + * @param context The context of this interaction. + * @return A pair containing the type of the tool (if the interaction was successful), and the result of the + * interaction. + * {@link InteractionResult#sidedSuccess(boolean)} will play the tool sound (based on the first element of + * the pair) and consume + * durability. */ public final Pair<@Nullable GTToolType, InteractionResult> onToolClick(ExtendedUseOnContext context) { // the side hit from the machine grid @@ -456,6 +487,9 @@ protected InteractionResult onScrewdriverClick(ExtendedUseOnContext context) { /** * Called when a machine is right clicked with an item. + * + * @param context The context which this interaction is being performed from. + * @return The result of this interaction callback. */ public InteractionResult onUseWithItem(ExtendedUseOnContext context) { var types = context.getToolType(); @@ -476,7 +510,11 @@ public InteractionResult onUseWithItem(ExtendedUseOnContext context) { } /** - * Called when a machine is right clicked without an item. + * Called when a machine is right clicked without an item, or if this machine was clicked with an item but no + * item-specific interaction was performed. + * + * @param context The context which this interaction is being performed from. + * @return The result of this interaction callback. */ public InteractionResult onUse(ExtendedUseOnContext context) { if (context.getPlayer().isShiftKeyDown()) { @@ -496,10 +534,18 @@ public InteractionResult onUse(ExtendedUseOnContext context) { /** * Called when a machine is left clicked. - * + * + * @param player Player that clicked + * @param hand Player hand + * @param face Clicked face * @return true to cancel the click event, false to continue processing */ public boolean onLeftClick(Player player, InteractionHand hand, @Nullable Direction face) { + for (var trait : getAllTraits()) { + if (trait instanceof IInteractionTrait interactionTrait) { + if (interactionTrait.onLeftClick(player, hand, face)) return true; + } + } return false; } @@ -515,16 +561,11 @@ public static MetaMachine getMachine(BlockGetter level, BlockPos pos) { return null; } - public void notifyBlockUpdate() { - if (getLevel() != null) { - getLevel().updateNeighborsAt(getBlockPos(), getLevel().getBlockState(getBlockPos()).getBlock()); - } - } - public @UnknownNullability Level getLevel() { return super.getLevel(); } + @ApiStatus.Internal public void setOwnerUUID(UUID uuid) { ownerUUID = uuid; syncDataHolder.markClientSyncFieldDirty("ownerUUID"); @@ -608,6 +649,11 @@ public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, I return null; } + /** + * Adds extra information to the F3 debug overlay when looking at this machine. + * + * @param lines A string consumer which lines are added to. + */ public void addDebugOverlayText(Consumer lines) { lines.accept(ChatFormatting.UNDERLINE + "Targeted Machine: "); lines.accept(this.getDefinition().getId().toString()); @@ -619,6 +665,11 @@ public void addDebugOverlayText(Consumer lines) { } } + /** + * The {@link MachineDefinition} of this machine. + * + * @return The {@link MachineDefinition} + */ public MachineDefinition getDefinition() { if (getBlockState().getBlock() instanceof MetaMachineBlock machineBlock) { return machineBlock.getDefinition(); @@ -628,31 +679,39 @@ public MachineDefinition getDefinition() { } } - public RotationState getRotationState() { - return getDefinition().getRotationState(); - } - /** * Called to obtain list of AxisAlignedBB used for collision testing, highlight rendering - * and ray tracing this meta tile entity's block in world + * and ray tracing this machine's block in world */ public void addCollisionBoundingBox(List collisionList) { collisionList.add(Shapes.block()); } - public static Direction getFrontFacing(@Nullable MetaMachine machine) { - return machine == null ? Direction.NORTH : machine.getFrontFacing(); - } - + /** + * Gets the direction which this machine is facing. + * + * @return The direction the machine is facing, or north if this machine does not have a front face. + */ public Direction getFrontFacing() { return getRotationState() == RotationState.NONE ? Direction.NORTH : getBlockState().getValue(getRotationState().property); } + /** + * Returns whether this machine has a front face. + * + * @return If this machine has a front face. + */ public final boolean hasFrontFacing() { return getRotationState() != RotationState.NONE; } + /** + * Returns whether this machine can be rotated to face a specific direction + * + * @param facing The direction to test + * @return If it is possible to rotate this machine to face the given direction. + */ public boolean isFacingValid(Direction facing) { if (hasFrontFacing() && facing == getFrontFacing()) return false; @@ -665,8 +724,23 @@ public boolean isFacingValid(Direction facing) { return getRotationState().test(facing); } + /** + * Returns the {@link RotationState} properties which this machine type supports. + * + * @return The {@link RotationState} + */ + public RotationState getRotationState() { + return getDefinition().getRotationState(); + } + + /** + * Rotates this machine to face a specific direction, if that direction is a valid facing direction. + * + * @param facing The new facing direction. + */ public void setFrontFacing(Direction facing) { var oldFacing = getFrontFacing(); + if (oldFacing == facing) return; if (allowExtendedFacing()) { var newUpwardsFacing = RelativeDirection.simulateAxisRotation(facing, oldFacing, getUpwardsFacing()); @@ -683,25 +757,21 @@ public void setFrontFacing(Direction facing) { } } - @MustBeInvokedByOverriders - public void updateModelData(ModelData.Builder builder) { - for (MachineTrait trait : getAllTraits()) { - if (trait instanceof IRenderingTrait renderingTrait) renderingTrait.updateModelData(builder); - } - } - - @Override - public ModelData getModelData() { - ModelData.Builder data = super.getModelData().derive(); - updateModelData(data); - return data.build(); - } - + /** + * Gets the direction which is this machine's upwards face. + * + * @return The upwards facing direction, or north if this machine does not allow extended facing. + */ public Direction getUpwardsFacing() { return this.allowExtendedFacing() ? this.getBlockState().getValue(GTBlockStateProperties.UPWARDS_FACING) : Direction.NORTH; } + /** + * Changes this machine's upwards facing direction, if this machine supports extended facing directions. + * + * @param upwardsFacing The new upwards facing direction. + */ public void setUpwardsFacing(Direction upwardsFacing) { if (!getDefinition().isAllowExtendedFacing()) { return; @@ -721,12 +791,29 @@ public void setUpwardsFacing(Direction upwardsFacing) { } } - public void onRotated(Direction oldFacing, Direction newFacing) {} - + /** + * Returns whether this machine supports extended facing directions. + * + * @return If extended facing directions are supported. + */ public boolean allowExtendedFacing() { return getDefinition().isAllowExtendedFacing(); } + /** + * Called when this machine is rotated + * + * @param oldFacing The previous facing direction + * @param newFacing The new facing direction + */ + public void onRotated(Direction oldFacing, Direction newFacing) {} + + /** + * Called by the block colour handler to get tint colour for a specific layer index + * + * @param index colour layer index + * @return Integer colour, or -1 to not apply a colour tint. + */ public int tintColor(int index) { // index < -100 => emission if shimmer is installed. if (index == 1 || index == -111) { @@ -735,23 +822,52 @@ public int tintColor(int index) { return -1; } - public void onNeighborChanged(Block block, BlockPos fromPos, boolean isMoving) { - getAllTraits().forEach(t -> t.onMachineNeighborChanged(block, fromPos, isMoving)); + /** + * @see ModelData + * @return ModelData to be passed to the {@link BakedModel} + */ + @Override + public ModelData getModelData() { + return super.getModelData().derive().build(); + } + + /** + * Called when a neighboring block is updated. + * + * @param neighborBlock The neighbor block type. + * @param neighborPos The neighbor position. + * @param isMoving If the neighbor block is moving (e.g. moved by a piston) + */ + public void onNeighborChanged(Block neighborBlock, BlockPos neighborPos, boolean isMoving) { + getAllTraits().forEach(t -> t.onMachineNeighborChanged(neighborBlock, neighborPos, isMoving)); } public void animateTick(RandomSource random) {} + /** + * Returns the {@link BlockState} that this block reports at a given side. + * + * @param level The level this block is in + * @param pos The block's position in the level + * @param side The side of the block that is being queried + * @param sourceState The state of the block that is querying the appearance, or {@code null} if not applicable + * @param sourcePos The position of the block that is querying the appearance, or {@code null} if not applicable + * @return The appearance of this block from the given side + * @see IForgeBlock#getAppearance(BlockState, BlockAndTintGetter, BlockPos, Direction, BlockState, BlockPos) + */ public BlockState getBlockAppearance(BlockState state, BlockAndTintGetter level, BlockPos pos, Direction side, @Nullable BlockState sourceState, @Nullable BlockPos sourcePos) { var appearance = getCoverContainer().getBlockAppearance(state, level, pos, side, sourceState, sourcePos); if (appearance != null) return appearance; - if (this instanceof IMultiPart part && part.isFormed()) { - appearance = part.getFormedAppearance(sourceState, sourcePos, side); - if (appearance != null) return appearance; - } return getDefinition().getAppearance().get(); } + /** + * Gets the current tick offset, which can be used to run code after a certain number of ticks. + * For example, {@code getOffsetTimer() % 20 == 0} will be true every 20 ticks (1 second) + * + * @return The current tick offset. + */ public final long getOffsetTimer() { if (getLevel() == null) return getOffset(); else if (getLevel().isClientSide()) return GTValues.CLIENT_TIME + getOffset(); @@ -770,31 +886,79 @@ public boolean isRemote() { // ***** Redstone Signals ****// //////////////////////////////// + /** + * Gets the redstone output signal at a specific side + * + * @param side Side + * @return Output signal + */ public int getOutputSignal(@Nullable Direction side) { if (side == null) return 0; // For some reason, Minecraft requests the output signal from the opposite side... CoverBehavior cover = getCoverContainer().getCoverAtSide(side.getOpposite()); - if (cover == null) return 0; - return cover.getRedstoneSignalOutput(); + if (cover != null) return cover.getRedstoneSignalOutput(); + + var signal = 0; + for (var trait : getAllTraits()) { + if (trait instanceof IRedstoneSignalTrait redstoneSignalTrait) { + signal = Math.max(signal, redstoneSignalTrait.getOutputSignal(side)); + } + } + + return signal; } + /** + * Gets the direct output signal at a specific side + * + * @param side Side + * @return Direct output signal + */ public int getOutputDirectSignal(@Nullable Direction side) { - // IDK what this does but MC wants it - return 0; + var signal = 0; + for (var trait : getAllTraits()) { + if (trait instanceof IRedstoneSignalTrait redstoneSignalTrait) { + signal = Math.max(signal, redstoneSignalTrait.getOutputDirectSignal(side)); + } + } + + return signal; } + /** + * Gets the analog (comparator) output signal + * + * @return Analog output signal. + */ public int getAnalogOutputSignal() { - return 0; + var signal = 0; + for (var trait : getAllTraits()) { + if (trait instanceof IRedstoneSignalTrait redstoneSignalTrait) { + signal = Math.max(signal, redstoneSignalTrait.getAnalogOutputSignal()); + } + } + + return signal; } + /** + * Returns if redstone can be connected to a specific side of this machine + * + * @param side The side to check + * @return If redstone can be connected + */ public boolean canConnectRedstone(Direction side) { - // For some reason, Minecraft requests the output signal from the opposite side... CoverBehavior cover = getCoverContainer().getCoverAtSide(side); - if (cover == null) return false; + if (cover != null) return cover.canConnectRedstone(); - return cover.canConnectRedstone(); + for (var trait : getAllTraits()) { + if (trait instanceof IRedstoneSignalTrait redstoneSignalTrait) { + if (redstoneSignalTrait.canConnectRedstone(side)) return true; + } + } + return false; } ////////////////////////////////////// @@ -863,6 +1027,13 @@ public AABB getRenderBoundingBox() { // ******** Capabilities *********// ////////////////////////////////////// + /** + * Gets the item filter for a specific side of this machine. + * + * @param side Side + * @param io The IO mode this filter should be applicable to. + * @return A {@code Predicate} representing this filter + */ public Predicate getItemCapFilter(@Nullable Direction side, IO io) { if (side != null) { var cover = getCoverContainer().getCoverAtSide(side); @@ -881,6 +1052,13 @@ public Predicate getItemCapFilter(@Nullable Direction side, IO io) { return item -> true; } + /** + * Gets the fluid filter for a specific side of this machine. + * + * @param side Side + * @param io The IO mode this filter should be applicable to. + * @return A {@code Predicate} representing this filter + */ public Predicate getFluidCapFilter(@Nullable Direction side, IO io) { if (side != null) { var cover = getCoverContainer().getCoverAtSide(side); @@ -899,6 +1077,13 @@ public Predicate getFluidCapFilter(@Nullable Direction side, IO io) return fluid -> true; } + /** + * Gets the item handler capability for a specific side of this machine + * + * @param side The side + * @param useCoverCapability Whether to return an item handler provided by an attached cover, if present. + * @return The {@link IItemHandlerModifiable} capability, or null. + */ @Nullable public IItemHandlerModifiable getItemHandlerCap(@Nullable Direction side, boolean useCoverCapability) { var list = getAllTraits().stream() @@ -924,6 +1109,13 @@ public IItemHandlerModifiable getItemHandlerCap(@Nullable Direction side, boolea return cover != null ? cover.getItemHandlerCap(handlerList) : handlerList; } + /** + * Gets the fluid handler capability for a specific side of this machine + * + * @param side The side + * @param useCoverCapability Whether to return a fluid handler provided by an attached cover, if present. + * @return The {@link IFluidHandlerModifiable} capability, or null. + */ @Nullable public IFluidHandlerModifiable getFluidHandlerCap(@Nullable Direction side, boolean useCoverCapability) { var list = getAllTraits().stream() diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java index 9471d9b130b..28afe1e2bfe 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java @@ -26,13 +26,15 @@ import com.google.common.collect.Tables; import it.unimi.dsi.fastutil.ints.Int2IntFunction; import lombok.Getter; -import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.EnumMap; import java.util.LinkedHashMap; import java.util.function.BiFunction; +/** + * All singleblock generators are implemented here. + */ public class SimpleGeneratorMachine extends WorkableTieredMachine implements IFancyUIMachine { @@ -84,7 +86,7 @@ public int tintColor(int index) { * @param recipe recipe * @return A {@link ModifierFunction} for the given Simple Generator */ - public static ModifierFunction recipeModifier(@NotNull MetaMachine machine, @NotNull GTRecipe recipe) { + public static ModifierFunction recipeModifier(MetaMachine machine, GTRecipe recipe) { if (!(machine instanceof SimpleGeneratorMachine generator)) { return RecipeModifier.nullWrongType(SimpleGeneratorMachine.class, machine); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java index d56136fdbf6..c6236776f7c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java @@ -4,7 +4,6 @@ import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; import com.gregtechceu.gtceu.api.gui.GuiTextures; import com.gregtechceu.gtceu.api.gui.editor.EditableUI; -import com.gregtechceu.gtceu.api.machine.feature.ITieredMachine; import com.gregtechceu.gtceu.api.machine.trait.NotifiableEnergyContainer; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; @@ -14,22 +13,21 @@ import com.lowdragmc.lowdraglib.gui.texture.ProgressTexture; import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; -import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.util.Mth; import lombok.Getter; import java.util.function.Function; -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class TieredEnergyMachine extends TieredMachine implements ITieredMachine { +/** + * A singleblock tiered machine with an energy container. + */ +public class TieredEnergyMachine extends TieredMachine { @SaveField @SyncToClient public final NotifiableEnergyContainer energyContainer; + @Getter protected final EnvironmentalExplosionTrait environmentalExplosionTrait; @@ -76,7 +74,7 @@ public int getAnalogOutputSignal() { } /** - * Determines max input or output amperage used by this meta tile entity + * Determines max input or output amperage used by this machine * if emitter, it determines size of energy packets it will emit at once * if receiver, it determines max input energy per request * @@ -87,7 +85,7 @@ protected long getMaxInputOutputAmperage() { } /** - * Determines if this meta tile entity is in energy receiver or emitter mode + * Determines if this machine is in energy receiver or emitter mode * * @return true if machine emits energy to network, false it it accepts energy from network */ diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java index 63fffde8fa3..f5b2553f098 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java @@ -20,6 +20,9 @@ import java.util.*; +/** + * A tiered energy machine with recipe logic and item/fluid IO. + */ public abstract class WorkableTieredMachine extends TieredEnergyMachine implements IRecipeLogicMachine, IMufflableMachine, IOverclockMachine { diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java index b3f03725c90..ec75796b409 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java @@ -1,6 +1,7 @@ package com.gregtechceu.gtceu.api.machine.feature.multiblock; import com.gregtechceu.gtceu.api.gui.fancy.TooltipsPanel; +import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.feature.IFancyUIMachine; import com.gregtechceu.gtceu.api.machine.feature.IMachineFeature; import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine; @@ -12,6 +13,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; +import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; @@ -23,37 +25,44 @@ public interface IMultiPart extends IMachineFeature, IFancyUIMachine { /** - * Can it be shared among multi multiblock. + * @return If this multi part can be shared between multiple multiblocks. */ default boolean canShared() { return true; } /** - * Whether it belongs to... + * If this multi part belongs to a controller at the given position + * + * @param controllerPos Controller position + * @return If this multi part belongs to a controller at the given position */ boolean hasController(BlockPos controllerPos); /** - * Whether it belongs to a formed Multiblock. + * @return If this multi part belongs to a formed multiblock. */ boolean isFormed(); /** - * Get this MultiPart's controllers + * Gets all controllers this multi part belongs to * - * @return An Unmodifiable View of the part's controllers + * @return An unmodifiable set containing the controllers. */ @UnmodifiableView SortedSet getControllers(); /** - * Called when it was removed from a multiblock. + * Called when this part is removed from a multiblock. + * + * @param controller The controller which this part has been removed from. */ void removedFromController(MultiblockControllerMachine controller); /** - * Called when it was added to a multiblock. + * Called when this part is added to a multiblock. + * + * @param controller The controller which this part has been added to */ void addedToController(MultiblockControllerMachine controller); @@ -63,14 +72,16 @@ default boolean canShared() { List getRecipeHandlers(); /** - * whether its base model can be replaced by controller when it is formed. + * If this part's base model can be replaced by controller when it is formed. */ default boolean replacePartModelWhenFormed() { return true; } /** - * get part's Appearance. same as IForgeBlock.getAppearance() / IFabricBlock.getAppearance() + * Called to get block appearance when this multi part is in a formed multiblock. + * + * @see MetaMachine#getBlockAppearance(BlockState, BlockAndTintGetter, BlockPos, Direction, BlockState, BlockPos) */ @Nullable default BlockState getFormedAppearance(BlockState sourceState, BlockPos sourcePos, Direction side) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java index dd31d974ca0..8e1ad857077 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java @@ -22,7 +22,6 @@ import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; -import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -36,13 +35,12 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault +/** + * The base class for all multiblock controllers + */ public class MultiblockControllerMachine extends MetaMachine { - private MultiblockState multiblockState; + private @Nullable MultiblockState multiblockState; private final List parts = new ArrayList<>(); private @Nullable ParallelHatchPartMachine parallelHatch = null; @Getter @@ -50,10 +48,10 @@ public class MultiblockControllerMachine extends MetaMachine { private BlockPos[] partPositions = new BlockPos[0]; /** - * Whether Multiblock Formed. + * If the multiblock is formed. *
- * NOTE: even machine is formed, it doesn't mean to workable! - * Its parts maybe invalid due to chunk unload. + * NOTE: Formed multiblocks may not be completely valid in some edge cases, e.g. when called on the same tick as a + * part becoming invalid */ @Getter @SaveField @@ -90,13 +88,8 @@ public void onUnload() { } /** - * Called when structure is formed, have to be called after {@link #checkPattern()}. (server-side / fake scene only) - *
- * Trigger points: - *
- * 1 - Blocks in structure changed but still formed. - *
- * 2 - Literally, structure formed. + * Called when multiblock structure becomes valid/formed. Called when blocks in structure change to form a valid + * multiblock, or when the controller is loaded. */ public void onStructureFormed() { isFormed = true; @@ -130,13 +123,8 @@ public void onStructureFormed() { } /** - * Called when structure is invalid. (server-side / fake scene only) - *
- * Trigger points: - *
- * 1 - Blocks in structure changed. - *
- * 2 - Before controller machine removed. + * Called when multiblock structure becomes invalid. Called when blocks in structure change, or when controller + * machine is about to be unloaded. */ public void onStructureInvalid() { isFormed = false; @@ -159,7 +147,7 @@ public void onStructureInvalid() { } /** - * Called from part, when part is invalid due to chunk unload or broken. + * Called when a multiblock part becomes invalid due to chunk unloading or block destruction. */ public void onPartUnload() { parts.removeIf(part -> part.self().isRemoved()); @@ -174,13 +162,20 @@ public void onPartUnload() { // ***** Getters ******// /// /////////////////////////////////// + /** + * The {@link MultiblockMachineDefinition} of this multiblock. + * + * @return The {@link MultiblockMachineDefinition} + */ @Override public MultiblockMachineDefinition getDefinition() { return (MultiblockMachineDefinition) super.getDefinition(); } /** - * Get MultiblockState. It records all structure-related information. + * Gets {@link MultiblockState}, which holds all structure-related information. + * + * @return The {@link MultiblockState} */ public MultiblockState getMultiblockState() { if (multiblockState == null) { @@ -202,7 +197,7 @@ public Comparator getPartSorter() { } /** - * Get all parts + * @return A list of all multiblock parts */ public List getParts() { // for the client side, when the chunk unloaded @@ -218,7 +213,7 @@ public List getParts() { } /** - * The instance of {@link ParallelHatchPartMachine} attached to this Controller. + * The instance of {@link ParallelHatchPartMachine} attached to this controller. *

* Note that this will return a singular instance, and will not account for multiple attached IParallelHatches * @@ -375,7 +370,7 @@ public void asyncCheckPattern(long periodID) { } /** - * Check MultiBlock Pattern. Just checking pattern without any other logic. + * Check Multiblock Pattern. Just checking pattern without any other logic. * You can override it but it's unsafe for calling. because it will also be called in an async thread. *
* you should always use {@link MultiblockControllerMachine#checkPatternWithLock()} )} and diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/MultiblockPartMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/MultiblockPartMachine.java index c3cccb81f8a..fd9279b8834 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/MultiblockPartMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/MultiblockPartMachine.java @@ -13,10 +13,10 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.client.model.machine.MachineRenderState; -import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -27,10 +27,9 @@ import java.util.*; -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault +/** + * The base class for all multiblock parts + */ public class MultiblockPartMachine extends MetaMachine implements IMultiPart { @SyncToClient @@ -161,8 +160,19 @@ public boolean replacePartModelWhenFormed() { @Override @Nullable - public BlockState getFormedAppearance(BlockState sourceState, BlockPos sourcePos, Direction side) { + public BlockState getFormedAppearance(@Nullable BlockState sourceState, @Nullable BlockPos sourcePos, + Direction side) { if (!replacePartModelWhenFormed()) return null; return IMultiPart.super.getFormedAppearance(sourceState, sourcePos, side); } + + @Override + public BlockState getBlockAppearance(BlockState state, BlockAndTintGetter level, BlockPos pos, Direction side, + @Nullable BlockState sourceState, @Nullable BlockPos sourcePos) { + if (isFormed()) { + var appearance = getFormedAppearance(sourceState, sourcePos, side); + if (appearance != null) return appearance; + } + return super.getBlockAppearance(state, level, pos, side, sourceState, sourcePos); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/package-info.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/package-info.java new file mode 100644 index 00000000000..64751bacff2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.api.machine.multiblock.part; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java index 157f5d80b25..e28634e50e4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java @@ -36,6 +36,9 @@ import java.util.*; +/** + * A singleblock steam machine with recipe logic and item IO. + */ public class SimpleSteamMachine extends SteamWorkableMachine implements IUIMachine { @SaveField diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamMachine.java index 9db36b37152..5d7943b3bed 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamMachine.java @@ -9,16 +9,14 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.common.data.GTMaterials; -import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraftforge.fluids.FluidType; import lombok.Getter; -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault +/** + * A singleblock machine with a steam tank. + */ public abstract class SteamMachine extends MetaMachine implements ITieredMachine { public static final BooleanProperty STEEL_PROPERTY = GTMachineModelProperties.IS_STEEL_MACHINE; diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java index 5c55b48e2e0..68a90d4de2b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java @@ -33,6 +33,9 @@ import java.util.*; +/** + * A singleblock steam machine with recipe logic. + */ public abstract class SteamWorkableMachine extends SteamMachine implements IRecipeLogicMachine, IMufflableMachine { diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTrait.java index aa0caefc9bd..c6d8669b9b4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTrait.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTrait.java @@ -8,7 +8,6 @@ import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; import com.gregtechceu.gtceu.common.machine.trait.CleanroomProviderTrait; -import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; @@ -16,19 +15,23 @@ import lombok.Getter; import lombok.Setter; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.function.Predicate; /** - * A machine trait represents a generic capability or behaviour that is attached to a machine. + * A machine trait represents a generic capability or behaviour that is attached to a machine.
+ *
* For example, machine traits may provide a recipe handler that can handle specific inputs/outputs of a recipe (e.g. - * {@link NotifiableItemStackHandler for items}). + * {@link NotifiableItemStackHandler} for items).
* Machine traits can also attach additional behaviours to a machine (e.g. {@link AutoOutputTrait}, - * {@link CleanroomProviderTrait}) + * {@link CleanroomProviderTrait})
+ *
+ * If a machine trait implements a capability interface, the trait will be returned by {@link MetaMachine#getCapability} + * if the machine trait's capability validator prediate is true for that side. */ -@MethodsReturnNonnullByDefault public abstract class MachineTrait implements ISyncManaged { @Getter @@ -37,15 +40,15 @@ public abstract class MachineTrait implements ISyncManaged { private @Nullable MetaMachine machine; @Setter protected Predicate<@Nullable Direction> capabilityValidator = $ -> true; + + /** + * The trait's callback priority. Traits with a higher priority will have their events fired + * first, which may prevent traits with a lower priority from handling some events. + */ @Getter @Setter private int traitPriority = 1; - public MachineTrait(MetaMachine machine) { - this.capabilityValidator = side -> true; - machine.getTraitHolder().attachTrait(this); - } - public MachineTrait() {} public MetaMachine getMachine() { @@ -63,6 +66,7 @@ protected List> validMachineClasses() { return List.of(); } + @ApiStatus.Internal public void setMachine(MetaMachine machine) { if (this.machine != null) throw new IllegalStateException("Machine trait already attached to a machine."); if (!validMachineClasses().isEmpty() && @@ -117,11 +121,29 @@ public void scheduleRenderUpdate() { getMachine().scheduleRenderUpdate(); } + /** + * Called when the machine is loaded. The entire world is not loaded when this method is called. + * To schedule code to run on the first full world tick, do + * {@code serverLevel.getServer().tell(new TickTask(0, CALLBACK))} + */ public void onMachineLoad() {} + /** + * Called when the machine is about to be unloaded. + */ public void onMachineUnload() {} + /** + * Called when the machine is destroyed. + */ public void onMachineDestroyed() {} - public void onMachineNeighborChanged(Block block, BlockPos fromPos, boolean isMoving) {} + /** + * Called when a neighboring block is updated. + * + * @param neighborBlock The neighbor block type. + * @param neighborPos The neighbor position. + * @param isMoving If the neighbor block is moving (e.g. moved by a piston) + */ + public void onMachineNeighborChanged(Block neighborBlock, BlockPos neighborPos, boolean isMoving) {} } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitHolder.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitHolder.java index 8447500dc54..decb4702f2e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitHolder.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitHolder.java @@ -57,6 +57,8 @@ public T attachTrait(T trait) { * @return The attached trait */ public T attachTrait(T trait, int callbackPriority) { + trait.setTraitPriority(callbackPriority); + var traitType = trait.getTraitType(); var list = traitsByType.computeIfAbsent(traitType, $ -> new ObjectArrayList<>(1)); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitType.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitType.java index aeb337615c7..b3a2fc7795b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/MachineTraitType.java @@ -1,17 +1,15 @@ package com.gregtechceu.gtceu.api.machine.trait; -import org.jetbrains.annotations.NotNull; - public final class MachineTraitType { private final Class clazz; private final boolean allowMultipleInstances; - public MachineTraitType(@NotNull Class clazz) { + public MachineTraitType(Class clazz) { this(clazz, true); } - public MachineTraitType(@NotNull Class clazz, boolean allowMultipleInstances) { + public MachineTraitType(Class clazz, boolean allowMultipleInstances) { this.clazz = clazz; this.allowMultipleInstances = allowMultipleInstances; } @@ -20,7 +18,7 @@ public boolean allowsMultipleInstances() { return allowMultipleInstances; } - public @NotNull T castTrait(@NotNull MachineTrait trait) { + public T castTrait(MachineTrait trait) { return clazz.cast(trait); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/NotifiableLaserContainer.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/NotifiableLaserContainer.java index 34d456bc761..0e3d5c0299a 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/NotifiableLaserContainer.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/NotifiableLaserContainer.java @@ -50,11 +50,11 @@ public void serverTick() { long amperesUsed = 0; for (Direction side : GTUtil.DIRECTIONS) { if (!outputsEnergy(side)) continue; - BlockEntity tileEntity = getMachine().getLevel().getBlockEntity(getMachine().getBlockPos().relative(side)); + BlockEntity be = getMachine().getLevel().getBlockEntity(getMachine().getBlockPos().relative(side)); Direction oppositeSide = side.getOpposite(); ILaserContainer laserContainer = GTCapabilityHelper.getLaser(getMachine().getLevel(), getMachine().getBlockPos().relative(side), oppositeSide); - if (tileEntity != null && laserContainer != null) { + if (be != null && laserContainer != null) { if (!laserContainer.inputsEnergy(oppositeSide)) continue; amperesUsed += laserContainer.acceptEnergyFromNetwork(oppositeSide, outputVoltage, outputAmperes - amperesUsed); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IFrontFacingTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IFrontFacingTrait.java index cff3a98b3fb..d3830476bb5 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IFrontFacingTrait.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IFrontFacingTrait.java @@ -9,6 +9,9 @@ public interface IFrontFacingTrait { /** * Returns if a machine can be rotated to be facing the given direction. + * + * @param direction The direction to check + * @return If the provided direction is a valid facing direction */ default boolean isValidFrontFace(Direction direction) { return true; diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IInteractionTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IInteractionTrait.java index aa1b4601f9d..d5ae3ed82b8 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IInteractionTrait.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IInteractionTrait.java @@ -3,9 +3,13 @@ import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; import com.mojang.datafixers.util.Pair; +import org.jetbrains.annotations.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -13,15 +17,42 @@ * A machine trait that provides special interaction behaviour. */ @ParametersAreNonnullByDefault -public interface IInteractionTrait extends ITraitFeature { +public interface IInteractionTrait { - /// Called when a player interacts with a machine without an item. + /** + * Called when a machine is right clicked without an item, or if this machine was clicked with an item but no + * item-specific interaction was performed. + * + * @param context The context which this interaction is being performed from. + * @return The result of this interaction callback. + */ default InteractionResult onUse(ExtendedUseOnContext context) { return InteractionResult.PASS; } - /// Called when a player interacts with a machine with a tool. - default Pair onToolClick(ExtendedUseOnContext context) { + /** + * Called when a player clicks this machine with a GT tool + * + * @param context The context of this interaction. + * @return A pair containing the type of the tool (if the interaction was successful), and the result of the + * interaction. + * {@link InteractionResult#sidedSuccess(boolean)} will play the tool sound (based on the first element of + * the pair) and consume + * durability. + */ + default Pair<@Nullable GTToolType, InteractionResult> onToolClick(ExtendedUseOnContext context) { return Pair.of(null, InteractionResult.PASS); } + + /** + * Called when a machine is left clicked. + * + * @param player Player that clicked + * @param hand Player hand + * @param face Clicked face + * @return true to cancel the click event, false to continue processing + */ + default boolean onLeftClick(Player player, InteractionHand hand, @Nullable Direction face) { + return false; + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRedstoneSignalTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRedstoneSignalTrait.java new file mode 100644 index 00000000000..0a6698c59ce --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRedstoneSignalTrait.java @@ -0,0 +1,48 @@ +package com.gregtechceu.gtceu.api.machine.trait.feature; + +import net.minecraft.core.Direction; + +import org.jetbrains.annotations.Nullable; + +// Trait for adding custom redstone signal outputs +public interface IRedstoneSignalTrait { + + /** + * Gets the redstone output signal at a specific side + * + * @param side Side + * @return Output signal + */ + default int getOutputSignal(@Nullable Direction side) { + return 0; + } + + /** + * Gets the direct output signal at a specific side + * + * @param side Side + * @return Direct output signal + */ + default int getOutputDirectSignal(@Nullable Direction side) { + return 0; + } + + /** + * Gets the analog (comparator) output signal + * + * @return Analog output signal. + */ + default int getAnalogOutputSignal() { + return 0; + } + + /** + * Returns if redstone can be connected to a specific side of this machine + * + * @param side The side to check + * @return If redstone can be connected + */ + default boolean canConnectRedstone(Direction side) { + return false; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java index bdf175dd2b2..6a2dc1a9296 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java @@ -9,22 +9,25 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.client.model.data.ModelData; import org.jetbrains.annotations.Nullable; import java.util.Set; -import javax.annotation.ParametersAreNonnullByDefault; - /** * A machine trait that overrides some of the default machine rendering behaviour. */ -@ParametersAreNonnullByDefault -public interface IRenderingTrait extends ITraitFeature { +public interface IRenderingTrait { /** - * Called when a player is looking at this machine, returns whether the grid overlay should be rendered. + * Called to determine if the grid overlay should be rendered on this machine. + * + * @param player Player looking at this machine + * @param pos Block pos + * @param state Block state + * @param held Item that player is holding + * @param toolTypes The GT tool types of the held item, if any + * @return If the grid overlay should be drawn on the machine. */ default boolean shouldRenderGridOverlay(Player player, BlockPos pos, BlockState state, ItemStack held, Set toolTypes) { @@ -34,12 +37,17 @@ default boolean shouldRenderGridOverlay(Player player, BlockPos pos, BlockState /** * Called when the machine grid overlay is being rendered to determine the icon to be rendered within the grid * segment on a specifc side. + * + * @param player Player looking at this machine + * @param pos Block pos + * @param state Block state + * @param toolTypes The GT tool types of the held item, if any + * @param side The machine side which this grid segment correspond to + * @return The icon to be rendered, or null */ default @Nullable ResourceTexture getGridOverlayIcon(Player player, BlockPos pos, BlockState state, Set toolTypes, Direction side) { return null; } - - default void updateModelData(ModelData.Builder builder) {} } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/ITraitFeature.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/ITraitFeature.java deleted file mode 100644 index 93694f7d2ea..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/ITraitFeature.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.trait.feature; - -//// Represents an aspect of MetaMachine behaviour which this trait modifies. -public interface ITraitFeature {} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/package-info.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/package-info.java new file mode 100644 index 00000000000..678ae8f66f5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.api.machine.trait.feature; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/multiblock/MultiblockMachineTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/multiblock/MultiblockMachineTrait.java index 0b745590200..ebf65460b7a 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/multiblock/MultiblockMachineTrait.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/multiblock/MultiblockMachineTrait.java @@ -5,6 +5,9 @@ import java.util.List; +/** + * A machine trait that is specific to multiblock controllers. + */ public abstract class MultiblockMachineTrait extends MachineTrait { public MultiblockMachineTrait() { @@ -21,7 +24,17 @@ protected List> validMachineClasses() { return List.of(MultiblockControllerMachine.class); } + /** + * Called when the multiblock structure is formed + * + * @see MultiblockControllerMachine#onStructureFormed() + */ public void onStructureFormed() {} + /** + * Called when the multiblock structure becomes invalid + * + * @see MultiblockControllerMachine#onStructureInvalid() + */ public void onStructureInvalid() {} } diff --git a/src/main/java/com/gregtechceu/gtceu/api/pattern/BlockPattern.java b/src/main/java/com/gregtechceu/gtceu/api/pattern/BlockPattern.java index afe594b39f5..22664ab9ad8 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pattern/BlockPattern.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pattern/BlockPattern.java @@ -148,7 +148,7 @@ public boolean checkPatternAt(MultiblockState worldState, BlockPos centerPos, Di } } boolean canPartShared = true; - if (worldState.getTileEntity() instanceof IMultiPart part) { // add detected parts + if (worldState.getBlockEntity() instanceof IMultiPart part) { // add detected parts if (!predicate.isAny()) { if (part.isFormed() && !part.canShared() && !part.hasController(worldState.controllerPos)) { // check part can be shared diff --git a/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockState.java b/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockState.java index 1cb071051bf..126686748a1 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockState.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockState.java @@ -34,8 +34,8 @@ public class MultiblockState { private BlockPos pos; private BlockState blockState; - private BlockEntity tileEntity; - private boolean tileEntityInitialized; + private BlockEntity blockEntity; + private boolean blockEntityInitialized; @Getter private final PatternMatchContext matchContext; @Getter @@ -72,8 +72,8 @@ public void clean() { public boolean update(BlockPos posIn, TraceabilityPredicate predicate) { this.pos = posIn; this.blockState = null; - this.tileEntity = null; - this.tileEntityInitialized = false; + this.blockEntity = null; + this.blockEntityInitialized = false; this.predicate = predicate; this.error = null; if (!world.isLoaded(posIn)) { @@ -116,16 +116,16 @@ public BlockState getBlockState() { } @Nullable - public BlockEntity getTileEntity() { + public BlockEntity getBlockEntity() { if (!getBlockState().hasBlockEntity()) { return null; } - if (this.tileEntity == null && !this.tileEntityInitialized) { - this.tileEntity = this.world.getBlockEntity(this.pos); - this.tileEntityInitialized = true; + if (this.blockEntity == null && !this.blockEntityInitialized) { + this.blockEntity = this.world.getBlockEntity(this.pos); + this.blockEntityInitialized = true; } - return this.tileEntity; + return this.blockEntity; } public BlockPos getPos() { diff --git a/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java b/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java index fcbab48ad80..e81b9250100 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pattern/Predicates.java @@ -314,8 +314,8 @@ public static TraceabilityPredicate frames(Material... frameMaterials) { .toArray(Block[]::new); return blocks(frameBlocks) .or(new TraceabilityPredicate(blockWorldState -> { - BlockEntity tileEntity = blockWorldState.getTileEntity(); - if (!(tileEntity instanceof IPipeNode pipeNode)) { + BlockEntity blockEntity = blockWorldState.getBlockEntity(); + if (!(blockEntity instanceof IPipeNode pipeNode)) { return false; } return ArrayUtils.contains(frameMaterials, pipeNode.getFrameMaterial()); diff --git a/src/main/java/com/gregtechceu/gtceu/api/pattern/predicates/SimplePredicate.java b/src/main/java/com/gregtechceu/gtceu/api/pattern/predicates/SimplePredicate.java index 552d450fed2..ab60fec77fc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pattern/predicates/SimplePredicate.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pattern/predicates/SimplePredicate.java @@ -132,9 +132,9 @@ private boolean checkInnerConditions(MultiblockState blockWorldState) { } } if (nbtParser != null && !blockWorldState.world.isClientSide) { - BlockEntity te = blockWorldState.getTileEntity(); - if (te != null) { - CompoundTag nbt = te.saveWithFullMetadata(); + BlockEntity be = blockWorldState.getBlockEntity(); + if (be != null) { + CompoundTag nbt = be.saveWithFullMetadata(); if (Pattern.compile(nbtParser).matcher(nbt.toString()).find()) { return true; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/pipenet/longdistance/ILDEndpoint.java b/src/main/java/com/gregtechceu/gtceu/api/pipenet/longdistance/ILDEndpoint.java index 17cea8f68f7..4ac73a8aeba 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pipenet/longdistance/ILDEndpoint.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pipenet/longdistance/ILDEndpoint.java @@ -79,8 +79,8 @@ default boolean isOutput() { @Nullable static ILDEndpoint tryGet(LevelAccessor world, BlockPos pos) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof ILDEndpoint endpoint) { + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof ILDEndpoint endpoint) { return endpoint; } return null; diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/MultiblockInWorldPreviewRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/MultiblockInWorldPreviewRenderer.java index c4bdbffa385..f690a0a418b 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/MultiblockInWorldPreviewRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/MultiblockInWorldPreviewRenderer.java @@ -432,7 +432,7 @@ private static void renderBlocks(TrackedDummyWorld level, PoseStack poseStack, B BlockState state = level.getBlockState(pos); FluidState fluidState = state.getFluidState(); Block block = state.getBlock(); - BlockEntity te = level.getBlockEntity(pos); + BlockEntity be = level.getBlockEntity(pos); if (block == Blocks.AIR) continue; diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java index c756537a1a8..2faca820792 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/ItemPipeBlockEntity.java @@ -139,7 +139,7 @@ public void resetTransferred() { * } * } *

- * if it was in a ticking TileEntity + * if it was in a ticking BlockEntity */ private void updateTransferredState() { long currentTime = getLevelTime(); diff --git a/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/FluidVoidingCover.java b/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/FluidVoidingCover.java index e940e453965..4eec280e777 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/FluidVoidingCover.java +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/FluidVoidingCover.java @@ -21,7 +21,6 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -120,13 +119,6 @@ public InteractionResult onSoftMalletClick(ExtendedUseOnContext context) { return InteractionResult.sidedSuccess(isRemote()); } - // TODO: Decide grid behavior - @Override - public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, ItemStack held, - Set toolTypes) { - return super.shouldRenderGrid(player, pos, state, held, toolTypes); - } - @Override public @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, Direction side) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/ItemVoidingCover.java b/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/ItemVoidingCover.java index 1a7740d401a..2c2a672d5ca 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/ItemVoidingCover.java +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/voiding/ItemVoidingCover.java @@ -116,13 +116,6 @@ public InteractionResult onSoftMalletClick(ExtendedUseOnContext context) { return InteractionResult.sidedSuccess(isRemote()); } - // TODO: Decide grid behavior - @Override - public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, ItemStack held, - Set toolTypes) { - return super.shouldRenderGrid(player, pos, state, held, toolTypes); - } - @Override public @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, Direction side) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/behavior/PortableScannerBehavior.java b/src/main/java/com/gregtechceu/gtceu/common/item/behavior/PortableScannerBehavior.java index cd7e83e856c..54db194be9a 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/behavior/PortableScannerBehavior.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/behavior/PortableScannerBehavior.java @@ -156,7 +156,7 @@ protected DisplayMode getMode(ItemStack stack) { } public int addScannerInfo(Player player, Level level, BlockPos pos, DisplayMode mode, List list) { - BlockEntity tileEntity = level.getBlockEntity(pos); + BlockEntity blockEntity = level.getBlockEntity(pos); int energyCost = 0; BlockState state = level.getBlockState(pos); @@ -195,7 +195,7 @@ public int addScannerInfo(Player player, Level level, BlockPos pos, DisplayMode } } - if (tileEntity instanceof MetaMachine machine) { + if (blockEntity instanceof MetaMachine machine) { list.add(Component.translatable(state.getBlock().getDescriptionId()).withStyle(ChatFormatting.BLUE)); @@ -216,7 +216,7 @@ public int addScannerInfo(Player player, Level level, BlockPos pos, DisplayMode } // Fluid tanks - Optional fluidCap = tileEntity.getCapability(ForgeCapabilities.FLUID_HANDLER).resolve(); + Optional fluidCap = blockEntity.getCapability(ForgeCapabilities.FLUID_HANDLER).resolve(); if (fluidCap.isPresent()) { list.add(Component.translatable("behavior.portable_scanner.divider")); IFluidHandler fluidHandler = fluidCap.get(); @@ -260,7 +260,7 @@ public int addScannerInfo(Player player, Level level, BlockPos pos, DisplayMode if (mode == DisplayMode.SHOW_ALL || mode == DisplayMode.SHOW_ELECTRICAL_INFO) { // Energy container - Optional energyCap = tileEntity + Optional energyCap = blockEntity .getCapability(GTCapability.CAPABILITY_ENERGY_CONTAINER).resolve(); if (energyCap.isPresent()) { IEnergyContainer energyContainer = energyCap.get(); @@ -343,8 +343,8 @@ public int addScannerInfo(Player player, Level level, BlockPos pos, DisplayMode // machine-specific info IDataInfoProvider provider = null; - if (tileEntity instanceof IDataInfoProvider) - provider = (IDataInfoProvider) tileEntity; + if (blockEntity instanceof IDataInfoProvider) + provider = (IDataInfoProvider) blockEntity; else if (machine instanceof IDataInfoProvider) provider = (IDataInfoProvider) machine; @@ -353,22 +353,22 @@ else if (machine instanceof IDataInfoProvider) list.addAll(provider.getDataInfo(mode)); } - } else if (tileEntity instanceof PipeBlockEntity pipe) { + } else if (blockEntity instanceof PipeBlockEntity pipe) { // Pipes need special name handling list.add(pipe.getPipeBlock().getName().withStyle(ChatFormatting.BLUE)); // Pipe-specific info - if (tileEntity instanceof IDataInfoProvider dataInfoProvider) { + if (blockEntity instanceof IDataInfoProvider dataInfoProvider) { list.add(Component.translatable("behavior.portable_scanner.divider")); list.addAll(dataInfoProvider.getDataInfo(mode)); } - if (tileEntity instanceof FluidPipeBlockEntity) { + if (blockEntity instanceof FluidPipeBlockEntity) { // Getting fluid info always costs 500 energyCost += 500; } - } else if (tileEntity instanceof IDataInfoProvider dataInfoProvider) { + } else if (blockEntity instanceof IDataInfoProvider dataInfoProvider) { list.add(Component.translatable("behavior.portable_scanner.divider")); list.addAll(dataInfoProvider.getDataInfo(mode)); } else { @@ -438,7 +438,7 @@ else if (machine instanceof IDataInfoProvider) } // Add optional debug info - if (tileEntity instanceof IDataInfoProvider dataInfoProvider) { + if (blockEntity instanceof IDataInfoProvider dataInfoProvider) { List debugInfo = dataInfoProvider.getDebugInfo(player, debugLevel, mode); if (debugInfo != null) { list.addAll(debugInfo); @@ -446,7 +446,7 @@ else if (machine instanceof IDataInfoProvider) } if (mode == DisplayMode.SHOW_INTERNAL_JAVA_INFO && - tileEntity instanceof ManagedSyncBlockEntity syncBlockEntity) { + blockEntity instanceof ManagedSyncBlockEntity syncBlockEntity) { MetaMachine machine = (syncBlockEntity instanceof MetaMachine m) ? m : null; PipeBlockEntity pipe = (syncBlockEntity instanceof PipeBlockEntity p) ? p : null; diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/BlockRotatingBehavior.java b/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/BlockRotatingBehavior.java index 9c50b46bfb0..1753106e602 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/BlockRotatingBehavior.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/tool/behavior/BlockRotatingBehavior.java @@ -49,9 +49,9 @@ public boolean canPerformAction(ItemStack stack, ToolAction action) { public InteractionResult onItemUseFirst(ItemStack stack, UseOnContext context) { Level level = context.getLevel(); BlockPos pos = context.getClickedPos(); - BlockEntity te = level.getBlockEntity(pos); - // MTEs have special handling on rotation - if (te instanceof MetaMachine) { + BlockEntity be = level.getBlockEntity(pos); + // Machines have special handling on rotation + if (be instanceof MetaMachine) { return InteractionResult.PASS; } diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CleanroomMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CleanroomMachine.java index 82966b9e9f7..b674b5520e0 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CleanroomMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/CleanroomMachine.java @@ -409,7 +409,7 @@ protected TraceabilityPredicate innerPredicate() { Set receivers = blockWorldState.getMatchContext().getOrCreate("cleanroomReceiver", Sets::newHashSet); // all non-GTMachines are allowed inside by default - BlockEntity blockEntity = blockWorldState.getTileEntity(); + BlockEntity blockEntity = blockWorldState.getBlockEntity(); if (blockEntity instanceof MetaMachine machine) { if (isMachineBanned(machine)) { return false; diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/OpticalDataHatchMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/OpticalDataHatchMachine.java index be745807be5..9b6f0253233 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/OpticalDataHatchMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/part/OpticalDataHatchMachine.java @@ -67,12 +67,12 @@ public boolean isRecipeAvailable(@NotNull GTRecipe recipe, @NotNull Collection onToolClick(ExtendedUseOnContext context) { + public Pair<@Nullable GTToolType, InteractionResult> onToolClick(ExtendedUseOnContext context) { var toolType = context.getToolType(); if (useDefaultToolHandlers) { if (toolType.contains(GTToolType.WRENCH)) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/BedrockOreMinerLogic.java b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/BedrockOreMinerLogic.java index c6c0d31ed3b..963ac93d9cf 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/BedrockOreMinerLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/BedrockOreMinerLogic.java @@ -44,7 +44,7 @@ public BedrockOreMinerMachine getMachine() { @Override protected List> validMachineClasses() { - return List.of(BedrockOreMinerLogic.class); + return List.of(BedrockOreMinerMachine.class); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/miner/MinerLogic.java b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/miner/MinerLogic.java index afb2f6edb14..b1af429b9ef 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/miner/MinerLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/miner/MinerLogic.java @@ -40,7 +40,6 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import lombok.Getter; import lombok.Setter; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -113,8 +112,7 @@ public class MinerLogic extends RecipeLogic implements IRecipeCapabilityHolder { private final Map> capabilitiesProxy; @Getter protected final Map, List>>> capabilitiesFlat; - private final ItemRecipeHandler inputItemHandler, outputItemHandler; - private final IgnoreEnergyRecipeHandler inputEnergyHandler; + private @Nullable ItemRecipeHandler inputItemHandler, outputItemHandler; @Setter @Getter private Direction dir = Direction.DOWN; @@ -136,17 +134,6 @@ public MinerLogic(int fortune, int speed, int maximumRadius) { this.pickaxeTool = GTMaterialItems.TOOL_ITEMS.get(GTMaterials.Neutronium, GTToolType.PICKAXE).get().get(); this.capabilitiesProxy = new EnumMap<>(IO.class); this.capabilitiesFlat = new EnumMap<>(IO.class); - this.inputItemHandler = new ItemRecipeHandler(IO.IN, - getRLMachine().getRecipeType().getMaxInputs(ItemRecipeCapability.CAP)); - this.outputItemHandler = new ItemRecipeHandler(IO.OUT, - getRLMachine().getRecipeType().getMaxOutputs(ItemRecipeCapability.CAP)); - this.inputEnergyHandler = new IgnoreEnergyRecipeHandler(); - - RecipeHandlerList inHandlers = RecipeHandlerList.of(IO.IN, inputItemHandler, inputEnergyHandler); - RecipeHandlerList outHandlers = RecipeHandlerList.of(IO.OUT, outputItemHandler); - - addHandlerList(inHandlers); - addHandlerList(outHandlers); } @Override @@ -159,6 +146,20 @@ protected List> validMachineClasses() { return List.of(IMiner.class); } + @Override + public void onMachineLoad() { + this.inputItemHandler = new ItemRecipeHandler(IO.IN, + getRLMachine().getRecipeType().getMaxInputs(ItemRecipeCapability.CAP)); + this.outputItemHandler = new ItemRecipeHandler(IO.OUT, + getRLMachine().getRecipeType().getMaxOutputs(ItemRecipeCapability.CAP)); + + RecipeHandlerList inHandlers = RecipeHandlerList.of(IO.IN, inputItemHandler, new IgnoreEnergyRecipeHandler()); + RecipeHandlerList outHandlers = RecipeHandlerList.of(IO.OUT, outputItemHandler); + + addHandlerList(inHandlers); + addHandlerList(outHandlers); + } + @Override public void resetRecipeLogic() { super.resetRecipeLogic(); @@ -360,8 +361,8 @@ protected boolean doPostProcessing(NonNullList blockDrops, BlockState if (oreDrop.isEmpty()) return false; // create dummy recipe handler - inputItemHandler.storage.setStackInSlot(0, oreDrop); - outputItemHandler.storage.clear(); + Objects.requireNonNull(inputItemHandler).storage.setStackInSlot(0, oreDrop); + Objects.requireNonNull(outputItemHandler).storage.clear(); var matches = getRLMachine().getRecipeType().searchRecipe(this, r -> RecipeHelper.matchContents(this, r).isSuccess()); @@ -431,23 +432,21 @@ private void mineAndInsertItems(NonNullList blockDrops, ServerLevel w // replace the ore block with cobblestone instead of breaking it to prevent mob spawning // remove the ore block's position from the mining queue var handler = getCachedItemHandler(); - if (handler != null) { - if (GTTransferUtils.addItemsToItemHandler(handler, true, blockDrops)) { - GTTransferUtils.addItemsToItemHandler(handler, false, blockDrops); - var pos = blocksToMine.getFirst(); - world.setBlock(pos, findMiningReplacementBlock(world, pos), 3); - mineX = pos.getX(); - mineZ = pos.getZ(); - mineY = pos.getY(); - blocksToMine.removeFirst(); - onMineOperation(); - - // if the inventory was previously considered full, mark it as not since an item was able to fit - isInventoryFull = false; - } else { - // the ore block was not able to fit, so the inventory is considered full - isInventoryFull = true; - } + if (GTTransferUtils.addItemsToItemHandler(handler, true, blockDrops)) { + GTTransferUtils.addItemsToItemHandler(handler, false, blockDrops); + var pos = blocksToMine.getFirst(); + world.setBlock(pos, findMiningReplacementBlock(world, pos), 3); + mineX = pos.getX(); + mineZ = pos.getZ(); + mineY = pos.getY(); + blocksToMine.removeFirst(); + onMineOperation(); + + // if the inventory was previously considered full, mark it as not since an item was able to fit + isInventoryFull = false; + } else { + // the ore block was not able to fit, so the inventory is considered full + isInventoryFull = true; } } @@ -457,7 +456,7 @@ private void mineAndInsertItems(NonNullList blockDrops, ServerLevel w * @param pos the {@link BlockPos} of the miner itself * @param currentRadius the currently set mining radius */ - public void initPos(@NotNull BlockPos pos, int currentRadius) { + public void initPos(BlockPos pos, int currentRadius) { x = pos.getX() - currentRadius; z = pos.getZ() - currentRadius; if (dir == Direction.UP) { @@ -581,7 +580,7 @@ private LinkedList getBlocksToMine() { * @param values to find the mean of * @return the mean value */ - private static long mean(@NotNull long[] values) { + private static long mean(long[] values) { if (values.length == 0L) return 0L; @@ -595,7 +594,7 @@ private static long mean(@NotNull long[] values) { * @param world the {@link Level} to get the average tick time of * @return the mean tick time */ - private static double getMeanTickTime(@NotNull Level world) { + private static double getMeanTickTime(Level world) { return mean(Objects.requireNonNull(world.getServer()).tickTimes) * 1.0E-6D; } diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index d06703ed5ec..091a1564988 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -838,8 +838,6 @@ public static void init(RegistrateLangProvider provider) { "Caused %s Lag Spike Warnings (anything taking longer than %sms) on the Server."); provider.add("behavior.portable_scanner.debug_machine", "Meta-ID: %s"); provider.add("behavior.portable_scanner.debug_machine_invalid", " invalid!"); - provider.add("behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =", - " null!"); provider.add("behavior.portable_scanner.debug_machine_valid", " valid"); provider.add("behavior.portable_scanner.divider", "========================="); provider.add("behavior.portable_scanner.energy_container_in", "Max IN: %s (%s) EU at %s A"); diff --git a/src/main/resources/assets/gtceu/lang/ja_jp.json b/src/main/resources/assets/gtceu/lang/ja_jp.json index f1d64562414..b13bab7d1af 100644 --- a/src/main/resources/assets/gtceu/lang/ja_jp.json +++ b/src/main/resources/assets/gtceu/lang/ja_jp.json @@ -14,7 +14,6 @@ "behavior.portable_scanner.debug_lag_count": "サーバーで %s 件のラグスパイク警告が発生 (%smsを超過した全てのオブジェクトが対象)", "behavior.portable_scanner.debug_machine": "メタ-ID: %s", "behavior.portable_scanner.debug_machine_invalid": " 無効", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " null", "behavior.portable_scanner.debug_machine_valid": " 妥当", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "最大入力: %s (%s) EU at %s A", diff --git a/src/main/resources/assets/gtceu/lang/pt_br.json b/src/main/resources/assets/gtceu/lang/pt_br.json index 4d3180e18dd..a659a61fe59 100644 --- a/src/main/resources/assets/gtceu/lang/pt_br.json +++ b/src/main/resources/assets/gtceu/lang/pt_br.json @@ -14,7 +14,6 @@ "behavior.portable_scanner.debug_lag_count": "Causou %s Avisos de Pico de Lag (qualquer coisa demorando mais que %sms) no Servidor.", "behavior.portable_scanner.debug_machine": "Meta-ID: %s", "behavior.portable_scanner.debug_machine_invalid": " inválido!", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " nulo!", "behavior.portable_scanner.debug_machine_valid": " válido", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "ENTRADA Máx: %s (%s) EU a %s A", diff --git a/src/main/resources/assets/gtceu/lang/ru_ru.json b/src/main/resources/assets/gtceu/lang/ru_ru.json index 8c90eb4ae69..46c481010d8 100644 --- a/src/main/resources/assets/gtceu/lang/ru_ru.json +++ b/src/main/resources/assets/gtceu/lang/ru_ru.json @@ -4483,7 +4483,6 @@ "behavior.data_item.assemblyline.data": "- §a%s", "behavior.data_item.assemblyline.title": "§nДанные для Сборочного конвейера:", "behavior.portable_scanner.debug_machine_invalid": " неверный!", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " null!", "behavior.portable_scanner.debug_machine_valid": " верный", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_out": "Макс. выход: %s (%s) EU при %s A", diff --git a/src/main/resources/assets/gtceu/lang/uk_ua.json b/src/main/resources/assets/gtceu/lang/uk_ua.json index d9acf9579b9..58d62ab4b4a 100644 --- a/src/main/resources/assets/gtceu/lang/uk_ua.json +++ b/src/main/resources/assets/gtceu/lang/uk_ua.json @@ -15,7 +15,6 @@ "behavior.portable_scanner.debug_lag_count": "Попередження про затримку %s (все, що триває довше, ніж %sмс) на сервері.", "behavior.portable_scanner.debug_machine": "Мета-ID: %s", "behavior.portable_scanner.debug_machine_invalid": " недійсний!", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " null!", "behavior.portable_scanner.debug_machine_valid": " дійсний", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "Макс. Вхід: %s (%s) EU з %s A", diff --git a/src/main/resources/assets/gtceu/lang/zh_cn.json b/src/main/resources/assets/gtceu/lang/zh_cn.json index f3a6663c821..3d375b7b9a6 100644 --- a/src/main/resources/assets/gtceu/lang/zh_cn.json +++ b/src/main/resources/assets/gtceu/lang/zh_cn.json @@ -14,7 +14,6 @@ "behavior.portable_scanner.debug_lag_count": "已在服务器中造成%s次延迟尖峰警告(任何大于%sms的情况)。", "behavior.portable_scanner.debug_machine": "元ID:%s", "behavior.portable_scanner.debug_machine_invalid": " 无效!", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " null!", "behavior.portable_scanner.debug_machine_valid": "无效!", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "输入上限:%s(%s)EU,%s A", diff --git a/src/main/resources/assets/gtceu/lang/zh_tw.json b/src/main/resources/assets/gtceu/lang/zh_tw.json index 15f79b5205b..527ecd8c330 100644 --- a/src/main/resources/assets/gtceu/lang/zh_tw.json +++ b/src/main/resources/assets/gtceu/lang/zh_tw.json @@ -14,7 +14,6 @@ "behavior.portable_scanner.debug_lag_count": "已在伺服器中造成%s次延遲尖峰警告(任何大於%sms的情況)。", "behavior.portable_scanner.debug_machine": "元ID:%s", "behavior.portable_scanner.debug_machine_invalid": " 無效!", - "behavior.portable_scanner.debug_machine_invalid_null=invalid! MetaTileEntity =": " null!", "behavior.portable_scanner.debug_machine_valid": "無效!", "behavior.portable_scanner.divider": "=========================", "behavior.portable_scanner.energy_container_in": "輸入上限:%s(%s)EU,%s A",