Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
045879f
split out some code into BlockGateAnd in preparation for more gates
Trinsdar Feb 15, 2026
6fc450c
added not gate
Trinsdar Feb 15, 2026
3e22867
added missing item for not gate
Trinsdar Feb 15, 2026
619bc47
renamed Not gate constant
Trinsdar Feb 15, 2026
03152eb
started working on not gate block models
Trinsdar Feb 15, 2026
e4a298f
moved gate models for better organization
Trinsdar Feb 16, 2026
2cd090d
finished models of not gate
Trinsdar Feb 16, 2026
6bbc378
added or and nor gates
Trinsdar Feb 16, 2026
7039d10
added models for buffer gate
Trinsdar Feb 18, 2026
089182a
added buffer gate
Trinsdar Feb 20, 2026
34657de
started work on models for xnor and xor gates
Trinsdar Feb 20, 2026
d8d08a5
added xor and xnor gates
Trinsdar Feb 21, 2026
7f39079
added block models for xnor gate
Trinsdar Feb 21, 2026
c3b3ea0
added full model for xor and xnor gate item models
Trinsdar Feb 22, 2026
eb41dc4
added rs latch
Trinsdar Feb 22, 2026
6b4c9d7
started work on models for toggle latch
Trinsdar Feb 22, 2026
bb7b9af
added toggle latch
Trinsdar Feb 22, 2026
5ee801f
added item model for toggle latch
Trinsdar Feb 22, 2026
f77fdfd
started work on gate baked model
Trinsdar Feb 23, 2026
88f5788
made all the gates use the new gate baked model
Trinsdar Feb 23, 2026
ed45edd
reenabled recipes for new gates
Trinsdar Feb 23, 2026
c1fe872
made getSidePower use SignalGetter instead of BlockGetter
Trinsdar Feb 23, 2026
6ff3cca
made BlockGateBase just output redstone based off whether that side i…
Trinsdar Feb 23, 2026
112d9e9
made IGateCondition use Object instead of Boolean so that other prope…
Trinsdar Feb 23, 2026
462008a
fixed recipes of new gates
Trinsdar Feb 23, 2026
b477e44
Merge branch '1.20.1' into new-gates
Trinsdar Feb 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/main/java/com/bluepowermod/block/gates/BlockGateAnd.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.bluepowermod.block.gates;

import com.bluepowermod.helper.DirectionHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.SignalGetter;
import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.state.BlockState;

import java.util.HashMap;
import java.util.Map;

public class BlockGateAnd extends BlockGateBase {
protected final boolean inverted;

public BlockGateAnd(boolean inverted){
this.inverted = inverted;
}

@Override
protected boolean isSideSource(Side side, BlockState blockState, BlockGetter blockAccess, BlockPos pos) {
return side == Side.FRONT;
}

@Override
public Map<Side, Byte> getSidePower(SignalGetter worldIn, BlockState state, BlockPos pos){
Map<Side, Byte> map = new HashMap<>();
Direction sideLeft = toDirection(Side.LEFT, state);
Direction sideRight = toDirection(Side.RIGHT, state);
Direction sideBack = toDirection(Side.BACK, state);
byte left = (byte) worldIn.getSignal(pos.relative(sideLeft), sideLeft);
byte right = (byte) worldIn.getSignal(pos.relative(sideRight), sideRight);
byte back = (byte) worldIn.getSignal(pos.relative(sideBack), sideBack);
map.put(Side.LEFT, left);
map.put(Side.RIGHT, right);
map.put(Side.BACK, back);
map.put(Side.FRONT, computeRedstone(Side.FRONT, back, (byte) 0, left, right));
return map;
}

public byte computeRedstone(Side side, byte back, byte front, byte left, byte right){
boolean and = left > 0 && right > 0 && back > 0;
return (byte) (and != inverted ? 16 : 0);
}}
94 changes: 52 additions & 42 deletions src/main/java/com/bluepowermod/block/gates/BlockGateBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.SignalGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.Rotation;
Expand All @@ -41,7 +42,7 @@
/**
* @author MoreThanHidden
*/
public class BlockGateBase extends BlockBase implements SimpleWaterloggedBlock {
public abstract class BlockGateBase extends BlockBase implements SimpleWaterloggedBlock {
public static final DirectionProperty FACING = BlockStateProperties.FACING;
public static final IntegerProperty ROTATION = IntegerProperty.create("rotation", 0, 3);
public static final BooleanProperty POWERED_FRONT = BooleanProperty.create("powered_front");
Expand Down Expand Up @@ -131,63 +132,72 @@ public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable L
.setValue(POWERED_RIGHT, map.get(Side.RIGHT) > 0));
}

@Override
public boolean isSignalSource(BlockState blockState) {
return true;
}

@Override
public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side){
Direction[] dirs = DirectionHelper.ArrayFromDirection(blockState.getValue(FACING));
if(side == dirs[blockState.getValue(ROTATION)]) {
Map<Side, Byte> map = getSidePower(blockAccess, blockState, pos);
return map.get(Side.FRONT);
Side side1 = fromDirection(side.getOpposite(), blockState.getValue(ROTATION), dirs);
if (isSideSource(side1, blockState, blockAccess, pos)){
return redstoneFromSide(side1, blockState);
}
return 0;
}

@Override
public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
Direction[] dirs = DirectionHelper.ArrayFromDirection(blockState.getValue(FACING));
if(side == dirs[blockState.getValue(ROTATION)]) {
Map<Side, Byte> map = getSidePower(blockAccess, blockState, pos);
return map.get(Side.FRONT);
Side side1 = fromDirection(side.getOpposite(), blockState.getValue(ROTATION), dirs);
if (isSideSource(side1, blockState, blockAccess, pos)){
return redstoneFromSide(side1, blockState);
}
return 0;
}

public Map<Side, Byte> getSidePower(BlockGetter worldIn, BlockState state, BlockPos pos){
Map<Side, Byte> map = new HashMap<>();
Direction[] dirs = DirectionHelper.ArrayFromDirection(state.getValue(FACING));
Direction side_left = dirs[state.getValue(ROTATION) == 3 ? 0 : state.getValue(ROTATION) + 1];
Direction side_right = side_left.getOpposite();
Direction side_back = dirs[state.getValue(ROTATION)];
BlockPos pos_left = pos.relative(side_left);
BlockPos pos_right = pos.relative(side_right);
BlockPos pos_back = pos.relative(side_back);
BlockState state_left = worldIn.getBlockState(pos_left);
BlockState state_right = worldIn.getBlockState(pos_right);
BlockState state_back = worldIn.getBlockState(pos_back);
byte left = (byte) state_left.getSignal(worldIn, pos_left, side_right);
byte right = (byte) state_right.getSignal(worldIn, pos_right, side_left);
byte back = (byte) state_back.getSignal(worldIn, pos_back, side_back.getOpposite());
if(state_left.getBlock() instanceof RedStoneWireBlock){left = state_left.getValue(RedStoneWireBlock.POWER).byteValue();}
if(state_right.getBlock() instanceof RedStoneWireBlock){right = state_right.getValue(RedStoneWireBlock.POWER).byteValue();}
if(state_back.getBlock() instanceof RedStoneWireBlock){back = state_back.getValue(RedStoneWireBlock.POWER).byteValue();}
map.put(Side.LEFT, left);
map.put(Side.RIGHT, right);
map.put(Side.BACK, back);
map.put(Side.FRONT, computeRedstone(Side.FRONT, back, (byte) 0, left, right));
return map;
}

public byte computeRedstone(Side side, byte back, byte front, byte left, byte right){
if (left > 0 && right > 0 ){
return (byte)(back > 0 ? 16 : 0);
}
return 0;
private int redstoneFromSide(Side side, BlockState state){
return switch (side){
case FRONT -> state.getValue(POWERED_FRONT) ? 16 : 0;
case BACK -> state.getValue(POWERED_BACK) ? 16 : 0;
case LEFT -> state.getValue(POWERED_LEFT) ? 16 : 0;
case RIGHT -> state.getValue(POWERED_RIGHT) ? 16 : 0;
};
}

protected Direction toDirection(Side side, BlockState state){
Direction[] dirs = DirectionHelper.ArrayFromDirection(state.getValue(FACING));
Direction left = dirs[state.getValue(ROTATION) == 3 ? 0 : state.getValue(ROTATION) + 1];
Direction back = dirs[state.getValue(ROTATION)];
return switch (side){
case FRONT -> back.getOpposite();
case BACK -> back;
case LEFT -> left;
case RIGHT -> left.getOpposite();
};
}

protected Side fromDirection(Direction direction, int rotation, Direction[] array){
Direction sideLeft = array[rotation == 3 ? 0 : rotation + 1];
Direction sideRight = sideLeft.getOpposite();
Direction sideBack = array[rotation];
Direction sideFront = sideBack.getOpposite();
if (direction == sideFront) return Side.FRONT;
if (direction == sideBack) return Side.BACK;
if (direction == sideLeft) return Side.LEFT;
if (direction == sideRight) return Side.RIGHT;
return null;
}

protected abstract Map<Side, Byte> getSidePower(SignalGetter worldIn, BlockState state, BlockPos pos);

protected boolean isSideSource(Side side, BlockState blockState, BlockGetter blockAccess, BlockPos pos){
return false;
}

@Override
public boolean isSignalSource(BlockState blockState) {
return true;
}



@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block blockIn, BlockPos fromPos, boolean bool) {
super.neighborChanged(state, world, pos, blockIn, fromPos, bool);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.bluepowermod.block.gates;

public class BlockGateBuffer extends BlockGateNot{
@Override
protected byte getOutput(byte back) {
return (byte) (back > 0 ? 16 : 0);
}
}
35 changes: 35 additions & 0 deletions src/main/java/com/bluepowermod/block/gates/BlockGateNot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.bluepowermod.block.gates;

import com.bluepowermod.helper.DirectionHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.SignalGetter;
import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.state.BlockState;

import java.util.HashMap;
import java.util.Map;

public class BlockGateNot extends BlockGateBase{
@Override
protected Map<Side, Byte> getSidePower(SignalGetter worldIn, BlockState state, BlockPos pos) {
Map<Side, Byte> map = new HashMap<>();
byte back = (byte) worldIn.getSignal(pos.relative(toDirection(Side.BACK, state)), toDirection(Side.BACK, state));
byte output = getOutput(back);
map.put(Side.FRONT, output);
map.put(Side.LEFT, output);
map.put(Side.RIGHT, output);
map.put(Side.BACK, back);
return map;
}

protected byte getOutput(byte back){
return (byte) (back > 0 ? 0 : 16);
}

@Override
protected boolean isSideSource(Side side, BlockState blockState, BlockGetter blockAccess, BlockPos pos) {
return side == Side.FRONT || side == Side.LEFT || side == Side.RIGHT;
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/bluepowermod/block/gates/BlockGateOr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.bluepowermod.block.gates;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;

import java.util.Map;

public class BlockGateOr extends BlockGateAnd{
public BlockGateOr(boolean inverted) {
super(inverted);
}

@Override
public byte computeRedstone(Side side, byte back, byte front, byte left, byte right) {
boolean output = back > 0 || left > 0 || right > 0;
return (byte) (output != inverted ? 16: 0);
}
}

53 changes: 53 additions & 0 deletions src/main/java/com/bluepowermod/block/gates/BlockGateRSLatch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.bluepowermod.block.gates;

import com.bluepowermod.helper.DirectionHelper;
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.SignalGetter;
import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

public class BlockGateRSLatch extends BlockGateBase{
@Override
protected Map<Side, Byte> getSidePower(SignalGetter worldIn, BlockState state, BlockPos pos) {
Direction sideLeft = toDirection(Side.LEFT, state);
Direction sideRight = toDirection(Side.RIGHT, state);
byte leftIn = (byte) worldIn.getSignal(pos.relative(sideLeft), sideLeft);
byte rightIn = (byte) worldIn.getSignal(pos.relative(sideRight), sideRight);
boolean frontPowered = state.getValue(POWERED_FRONT);
boolean backPowered = state.getValue(POWERED_BACK);
if (!frontPowered && !backPowered ){
if (rightIn == 0) backPowered = true;
else if (leftIn == 0) frontPowered = true;
}
if (leftIn > 0 && rightIn > 0){
frontPowered = false;
backPowered = false;
} else if (leftIn > 0 && frontPowered){
frontPowered = false;
backPowered = true;
} else if (rightIn > 0 && backPowered){
backPowered = false;
frontPowered = true;
}
return Map.of(Side.FRONT, (byte) (frontPowered ? 16 : 0),
Side.LEFT, (byte)(backPowered || leftIn > 0 ? 16 : 0),
Side.RIGHT, (byte)(frontPowered || rightIn > 0 ? 16 : 0),
Side.BACK, (byte)(backPowered ? 16 : 0));
}

@Override
protected boolean isSideSource(Side side, BlockState blockState, BlockGetter blockAccess, BlockPos pos) {
return side == Side.FRONT || side == Side.BACK || (side == Side.LEFT && blockState.getValue(POWERED_BACK) || (side == Side.RIGHT && blockState.getValue(POWERED_FRONT)));
}

@Override
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
return super.getStateForPlacement(context).setValue(POWERED_FRONT, true).setValue(POWERED_RIGHT, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.bluepowermod.block.gates;

import com.bluepowermod.helper.DirectionHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.SignalGetter;
import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

public class BlockGateToggleLatch extends BlockGateBase{
@Override
protected Map<Side, Byte> getSidePower(SignalGetter worldIn, BlockState state, BlockPos pos) {
Direction sideLeft = toDirection(Side.LEFT, state);
Direction sideRight = toDirection(Side.RIGHT, state);
byte leftIn = (byte) worldIn.getSignal(pos.relative(sideLeft), sideLeft);
byte rightIn = (byte) worldIn.getSignal(pos.relative(sideRight), sideRight);
boolean frontPowered = state.getValue(POWERED_FRONT);
boolean backPowered = state.getValue(POWERED_BACK);
boolean leftPowered = state.getValue(POWERED_LEFT);
boolean rightPowered = state.getValue(POWERED_RIGHT);
if (leftPowered || rightPowered){ // Do nothing
return Map.of(Side.FRONT, (byte) (frontPowered ? 16 : 0),
Side.LEFT, leftIn,
Side.RIGHT, rightIn,
Side.BACK, (byte)(backPowered ? 16 : 0));

}
if (leftIn > 0 || rightIn > 0){
frontPowered = !frontPowered;
backPowered = !backPowered;
}
return Map.of(Side.FRONT, (byte) (frontPowered ? 16 : 0),
Side.LEFT, leftIn,
Side.RIGHT, rightIn,
Side.BACK, (byte)(backPowered ? 16 : 0));
}

@Override
protected boolean isSideSource(Side side, BlockState blockState, BlockGetter blockAccess, BlockPos pos) {
return side == Side.FRONT || side == Side.BACK;
}

@Override
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
return super.getStateForPlacement(context).setValue(POWERED_FRONT, true);
}

@Override
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
state = state.setValue(POWERED_FRONT, !state.getValue(POWERED_FRONT)).setValue(POWERED_BACK, !state.getValue(POWERED_BACK));
level.setBlockAndUpdate(pos, state);
for (Direction dir : DirectionHelper.ArrayFromDirection(state.getValue(FACING))){
BlockPos neighbor = pos.relative(dir);
BlockState neighborState = level.getBlockState(neighbor);
level.updateNeighborsAtExceptFromFacing(neighbor, neighborState.getBlock(), dir.getOpposite());
}
level.playSound(null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, 0.5F);
return InteractionResult.sidedSuccess(level.isClientSide);
}
}
Loading