Skip to content

Instantly share code, notes, and snippets.

@Lanse505
Created August 3, 2022 12:08
Show Gist options
  • Save Lanse505/565cd0876b104151442017a7fe7b351c to your computer and use it in GitHub Desktop.
Save Lanse505/565cd0876b104151442017a7fe7b351c to your computer and use it in GitHub Desktop.
package matteroverdrive.core.block;
import com.hrznstudio.titanium.block.RotatableBlock.RotationType;
import com.hrznstudio.titanium.block.RotationHandler;
import com.hrznstudio.titanium.block.tile.BasicTile;
import matteroverdrive.core.block.state.StateVariables;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class GenericStateVariableBlock<T extends BasicTile<T>> extends GenericEntityBlock<T> {
/**
* The immutable {@link StateVariables} object for the block.
*/
private final StateVariables stateVariables;
/**
* Default Constructor for GenericStateVariableBlock.
*
* @param properties The blocks BlockBehaviour Properties.
* @param stateVariables The state variables for the block.
* @param name The "name" of the block (IE. "charger_block")
* @param tileClass The BlockEntity Class for the block.
*/
protected GenericStateVariableBlock(Properties properties, StateVariables stateVariables, String name, Class<T> tileClass) {
super(properties, name, tileClass);
this.stateVariables = stateVariables;
BlockState defaultState = getStateDefinition().any();
if (stateVariables.canBeWaterlogged()) {
defaultState.setValue(BlockStateProperties.WATERLOGGED, false);
}
if (stateVariables.canBeLit()) {
defaultState.setValue(BlockStateProperties.LIT, false);
}
registerDefaultState(defaultState);
}
/**
* Creates our default {@link StateDefinition}.
* In our case:
* - If the value of the local {@link StateVariables#canBeWaterlogged()} is true then it adds the {@link BlockStateProperties#WATERLOGGED} property.
* - If our {@link StateVariables#getRotationType()} )'s "property" list isn't null then we can add the associated properties of our {@link RotationType}.
*
* @param builder The passed in {@link StateDefinition.Builder} for adding the properties to.
*/
@Override
protected void createBlockStateDefinition(@NotNull StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
if (this.stateVariables.canBeWaterlogged()) {
builder.add(BlockStateProperties.WATERLOGGED);
}
if (this.stateVariables.getRotationType().getProperties().length > 0) {
builder.add(this.stateVariables.getRotationType().getProperties());
}
if (this.stateVariables.canBeLit()) {
builder.add(BlockStateProperties.LIT);
}
}
/**
* Getter for RotationType.
*
* @return returns the blocks {@link RotationType}.
*/
public RotationType getRotationType() {
return stateVariables.getRotationType();
}
/**
* Logic goes:
* 1. Get the Default {@link BlockState} + Modifications by the {@link RotationHandler}.
* 2. Get the {@link FluidState} -> If the fluidstate is of type {@link Fluids#WATER} then set the value of {@link BlockStateProperties#WATERLOGGED} to true.
*
* @param context The context for the block placement.
* @return Returns the BlockState of the placed block to use.
*/
@Nullable
@Override
public BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
BlockState stateWithRotation = this.getRotationType().getHandler().getStateForPlacement(this, context);
FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos());
return fluidState.getType() == Fluids.WATER ? stateWithRotation.setValue(BlockStateProperties.WATERLOGGED, true) : stateWithRotation;
}
/**
* Used to update the fluid if need be, by scheduling a fluid tick with a delayed value.
*
* @param state The {@link BlockState} of the {@link Block} whose shape needs updating.
* @param direction The direction of the {@link Block}.
* @param neighborState The neighbouring {@link BlockState}.
* @param level The {@link Level} of the {@link Block}.
* @param currentPos The current {@link BlockPos} of the {@link Block}.
* @param neighborPos The neighbouring {@link Block}'s {@link BlockPos}.
* @return Returns the blocks state unless modifications occur.
*/
@SuppressWarnings("deprecation")
@Override
public @NotNull BlockState updateShape(BlockState state, @NotNull Direction direction,
@NotNull BlockState neighborState, @NotNull LevelAccessor level,
@NotNull BlockPos currentPos, @NotNull BlockPos neighborPos) {
if (getProperty(state, BlockStateProperties.WATERLOGGED) != null) {
level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
}
return super.updateShape(state, direction, neighborState, level, currentPos, neighborPos);
}
/**
* Override the default getFluidState method to be able to return the Water fluid if the block is waterlogged.
*
* @param state The {@link BlockState} of the {@link Block}.
* @return Returns the {@link FluidState} of the {@link Block}.
*/
@SuppressWarnings("deprecation")
@Override
public @NotNull FluidState getFluidState(BlockState state) {
return getProperty(state, BlockStateProperties.WATERLOGGED) != null ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}
/**
* Rotates our {@link Block} using our blocks provided {@link RotationType} handler.
*
* @param state The current {@link BlockState} of the {@link Block}.
* @param rotation The current {@link Rotation} of the {@link Block}.
* @return Returns the new state of the block.
*/
@SuppressWarnings("deprecation")
@Override
public @NotNull BlockState rotate(@NotNull BlockState state, @NotNull Rotation rotation) {
if (getRotationType().getProperties().length > 0){
return state.setValue(getRotationType().getProperties()[0], rotation.rotate(state.getValue(getRotationType().getProperties()[0])));
}
return super.rotate(state, rotation);
}
/**
* Mirrors our {@link Block} using our blocks provided {@link RotationType} handler.
*
* @param state The current {@link BlockState} of the {@link Block}.
* @param mirror The current {@link Mirror} state of the {@link Block}.
* @return Returns the new state of the block.
*/
@SuppressWarnings("deprecation")
@Override
public @NotNull BlockState mirror(@NotNull BlockState state, @NotNull Mirror mirror) {
if (getRotationType().getProperties().length > 0){
return state.rotate(mirror.getRotation(state.getValue(getRotationType().getProperties()[0])));
}
return super.mirror(state, mirror);
}
/**
* @param state
* @param level
* @param pos
* @return
*/
@Override
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
return getProperty(state, BlockStateProperties.LIT) != null ? 15 : super.getLightEmission(state, level, pos);
}
public DirectionProperty getRotationProperty() {
return getRotationType().getProperties()[0];
}
@Nullable
public <U extends Comparable<U>> U getProperty(BlockState state, Property<U> property) {
if (state.hasProperty(property)) {
return state.getValue(property);
}
return null;
}
}
package matteroverdrive.core.block.state;
import com.hrznstudio.titanium.block.RotatableBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import javax.annotation.Nonnull;
public class StateVariables {
/**
* The {@link Boolean} value which states if the block can be waterlogged or not.
*/
private final boolean canBeWaterlogged;
/**
* The {@link RotatableBlock.RotationType} of the Block.
*/
@Nonnull
private final RotatableBlock.RotationType rotationType;
/**
* The {@link Boolean} value which states if the block can be lit or not.
*/
private final boolean canBeLit;
/**
* Empty Private Constructor to make it so people don't instantiate new objects directly.
*/
private StateVariables(final boolean isWaterloggable, @Nonnull final RotatableBlock.RotationType rotationType, final boolean canBeLit) {
this.canBeWaterlogged = isWaterloggable;
this.rotationType = rotationType;
this.canBeLit = canBeLit;
}
/**
* @return Returns a new {@link StateVariables.Builder} object.
*/
public static Builder getBuilder() {
return new Builder();
}
/**
* Copies another {@link StateVariables} object's properties into a new {@link Builder} object.
*
* @param variables The existing {@link StateVariables} object.
* @return Returns a mutable {@link Builder} that inherits the values of the immutable {@link StateVariables} object passed in.
*/
public static Builder copy(StateVariables variables) {
Builder copy = getBuilder();
copy.canBeWaterlogged = variables.canBeWaterlogged;
copy.rotationType = variables.rotationType;
return copy;
}
/**
* @return Returns the value of {@link #canBeWaterlogged}.
*/
public boolean canBeWaterlogged() {
return canBeWaterlogged;
}
/**
* @return Returns the value of {@link #rotationType}.
*/
@Nonnull
public RotatableBlock.RotationType getRotationType() {
return rotationType;
}
/**
* @return Returns the value of {@link #canBeLit}
*/
public boolean canBeLit() {
return canBeLit;
}
/**
* The mutable {@link Builder} object for the {@link StateVariables}.
*/
public static class Builder {
/**
* The value stating if the block should be waterlogged or not.
*/
boolean canBeWaterlogged = false;
/**
* The {@link RotatableBlock.RotationType} of the Block.
*/
@Nonnull
RotatableBlock.RotationType rotationType = RotatableBlock.RotationType.NONE;
/**
* The value stating if the block can be lit or not.
*/
boolean canBeLit = false;
/**
* Default Constructor
*/
public Builder() {}
/**
* Used to specify if the {@link Block} can be waterlogged, and thus should implement the {@link BlockStateProperties#WATERLOGGED} property.
*
* @return Returns the builder.
*/
public Builder canBeWaterlogged() {
this.canBeWaterlogged = true;
return this;
}
/**
* Used to specify the
*
* @param rotationType The {@link RotatableBlock.RotationType} enum to use for rotation handling for the block.
* @return Returns the builder.
*/
public Builder withRotationType(@Nonnull RotatableBlock.RotationType rotationType) {
this.rotationType = rotationType;
return this;
}
public Builder canBeLit() {
this.canBeLit = true;
return this;
}
/**
* @return Returns the immutable {@link StateVariables} object.
*/
public StateVariables build() {
return new StateVariables(canBeWaterlogged, rotationType, canBeLit);
}
}
public static class Defaults {
// No Rotation
/**
* Default Machine (No States)
*/
public static final StateVariables defaultMachine = StateVariables.getBuilder().build();
/**
* Default Machine /w LIT state
*/
public static final StateVariables litMachine = StateVariables.copy(defaultMachine)
.canBeLit().build();
/**
* Default Machine /w Waterloggable state
*/
public static final StateVariables waterloggableMachine = StateVariables.copy(defaultMachine)
.canBeWaterlogged().build();
/**
* Default Machine /w LIT & Waterloggable states
*/
public static final StateVariables waterloggableLit = StateVariables.copy(waterloggableMachine)
.canBeLit().build();
// With Rotations;
/**
* Defaults with Four-Way & Six-Way Rotations
*/
public static final StateVariables defaultFourWay = StateVariables.copy(defaultMachine)
.withRotationType(RotatableBlock.RotationType.FOUR_WAY).build();
public static final StateVariables defaultSixWay = StateVariables.copy(defaultMachine)
.withRotationType(RotatableBlock.RotationType.SIX_WAY).build();
public static final StateVariables litFourWay = StateVariables.copy(litMachine)
.withRotationType(RotatableBlock.RotationType.FOUR_WAY).build();
public static final StateVariables litSixWay = StateVariables.copy(litMachine)
.withRotationType(RotatableBlock.RotationType.SIX_WAY).build();
public static final StateVariables waterloggableFourway = StateVariables.copy(waterloggableMachine)
.withRotationType(RotatableBlock.RotationType.FOUR_WAY).build();
public static final StateVariables waterloggableSixway = StateVariables.copy(waterloggableMachine)
.withRotationType(RotatableBlock.RotationType.SIX_WAY).build();
public static final StateVariables waterloggableLitFourway = StateVariables.copy(waterloggableLit)
.withRotationType(RotatableBlock.RotationType.FOUR_WAY).build();
public static final StateVariables waterloggableLitSixway = StateVariables.copy(waterloggableLit)
.withRotationType(RotatableBlock.RotationType.SIX_WAY).build();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment