finished bluestone, antimetal rails, nyxite button and pressure plate, various other tweaks and fixes

This commit is contained in:
craisinlord committed 2026-07-24 02:35:28 -05:00
1 parent b37b49dff1
commit 2795134604
180 files changed
+4565 -238

No files matched your search

@@ -0,0 +1,87 @@
package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.content.minecart.AntimetalRailHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.BaseRailBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public abstract class AbstractAntimetalRailBlock extends BaseRailBlock {
protected static final VoxelShape CEILING_FLAT_SHAPE = Block.box(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D);
protected static final VoxelShape CEILING_SLOPE_SHAPE = Block.box(0.0D, 6.0D, 0.0D, 16.0D, 16.0D, 16.0D);
protected AbstractAntimetalRailBlock(boolean isStraight, BlockBehaviour.Properties properties) {
super(isStraight, properties);
}
public static boolean isAntimetalRail(BlockState state) {
return state.getBlock() instanceof AbstractAntimetalRailBlock;
}
public static boolean hasCeilingSupport(LevelReader level, BlockPos pos) {
return Block.canSupportCenter(level, pos.above(), Direction.DOWN);
}
@Override
protected VoxelShape getShape(BlockState state, net.minecraft.world.level.BlockGetter level, BlockPos pos, CollisionContext context) {
RailShape shape = state.getValue(getShapeProperty());
return shape.isAscending() ? CEILING_SLOPE_SHAPE : CEILING_FLAT_SHAPE;
}
@Override
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
return hasCeilingSupport(level, pos);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
if (context.getClickedFace() != Direction.DOWN && context.getClickedFace() != Direction.UP && !context.replacingClickedOnBlock()) {
return null;
}
if (!hasCeilingSupport(context.getLevel(), context.getClickedPos())) {
return null;
}
return AntimetalRailHelper.getStateForPlacement(this, context);
}
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (!state.canSurvive(level, pos)) {
return Blocks.AIR.defaultBlockState();
}
if (direction != Direction.DOWN && direction != Direction.UP) {
AntimetalRailHelper.updateConnections(this, state, level, pos);
}
return state;
}
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
if (!oldState.is(state.getBlock())) {
AntimetalRailHelper.updateConnections(this, state, level, pos);
}
}
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) {
if (level.isClientSide()) {
return;
}
if (!state.canSurvive(level, pos)) {
dropResources(state, level, pos);
level.removeBlock(pos, movedByPiston);
return;
}
AntimetalRailHelper.updateConnections(this, state, level, pos);
}
}
@@ -26,7 +26,7 @@ public abstract class AbstractCeilingBluestoneBlock extends Block {
@Override @Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (!state.canSurvive(level, pos)) { if (direction == Direction.UP && !state.canSurvive(level, pos)) {
return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState();
} }
return super.updateShape(state, direction, neighborState, level, pos, neighborPos); return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
@@ -26,7 +26,7 @@ public abstract class AbstractCeilingDiodeBlock extends DiodeBlock {
@Override @Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (!state.canSurvive(level, pos)) { if (direction == Direction.UP && !state.canSurvive(level, pos)) {
return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState();
} }
return super.updateShape(state, direction, neighborState, level, pos, neighborPos); return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
@@ -0,0 +1,65 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
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.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.RailShape;
public class AntimetalActivatorRailBlock extends AbstractAntimetalRailBlock {
public static final MapCodec<AntimetalActivatorRailBlock> CODEC = simpleCodec(AntimetalActivatorRailBlock::new);
public static final EnumProperty<RailShape> SHAPE = BlockStateProperties.RAIL_SHAPE_STRAIGHT;
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
public AntimetalActivatorRailBlock(BlockBehaviour.Properties properties) {
super(true, properties);
this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, RailShape.NORTH_SOUTH).setValue(POWERED, false).setValue(WATERLOGGED, false));
}
@Override
protected MapCodec<? extends AbstractAntimetalRailBlock> codec() {
return CODEC;
}
@Override
public Property<RailShape> getShapeProperty() {
return SHAPE;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SHAPE, POWERED, WATERLOGGED);
}
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) {
super.neighborChanged(state, level, pos, neighborBlock, neighborPos, movedByPiston);
updatePoweredState(level, pos, level.getBlockState(pos));
}
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
super.onPlace(state, level, pos, oldState, movedByPiston);
if (!oldState.is(state.getBlock())) {
updatePoweredState(level, pos, level.getBlockState(pos));
}
}
private void updatePoweredState(Level level, BlockPos pos, BlockState state) {
if (level.isClientSide() || !(state.getBlock() instanceof AntimetalActivatorRailBlock)) {
return;
}
boolean powered = AntimetalPowerHelper.isPoweredWithChain(level, pos, state, SHAPE, AntimetalActivatorRailBlock.class);
if (state.getValue(POWERED) != powered) {
level.setBlock(pos, state.setValue(POWERED, powered), 3);
AntimetalPowerHelper.notifyAllSignalNeighbors(level, pos);
}
}
}
@@ -0,0 +1,110 @@
package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.content.minecart.AntimetalMinecartAccess;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.Container;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
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.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.phys.AABB;
import java.util.List;
public class AntimetalDetectorRailBlock extends AbstractAntimetalRailBlock {
public static final MapCodec<AntimetalDetectorRailBlock> CODEC = simpleCodec(AntimetalDetectorRailBlock::new);
public static final EnumProperty<RailShape> SHAPE = BlockStateProperties.RAIL_SHAPE_STRAIGHT;
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
private static final int CHECK_PERIOD = 20;
public AntimetalDetectorRailBlock(BlockBehaviour.Properties properties) {
super(true, properties);
this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, RailShape.NORTH_SOUTH).setValue(POWERED, false).setValue(WATERLOGGED, false));
}
@Override
protected MapCodec<? extends AbstractAntimetalRailBlock> codec() {
return CODEC;
}
@Override
public Property<RailShape> getShapeProperty() {
return SHAPE;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SHAPE, POWERED, WATERLOGGED);
}
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
super.onPlace(state, level, pos, oldState, movedByPiston);
if (!oldState.is(state.getBlock()) && !level.isClientSide()) {
level.scheduleTick(pos, this, CHECK_PERIOD);
}
}
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
boolean detected = !getDetectedCarts(level, pos).isEmpty();
if (detected != state.getValue(POWERED)) {
level.setBlock(pos, state.setValue(POWERED, detected), 3);
AntimetalPowerHelper.notifyAllSignalNeighbors(level, pos);
}
level.scheduleTick(pos, this, CHECK_PERIOD);
}
private static List<AbstractMinecart> getDetectedCarts(Level level, BlockPos pos) {
AABB box = new AABB(pos.getX(), pos.getY() - 2.0D, pos.getZ(), pos.getX() + 1.0D, pos.getY() + 1.0D, pos.getZ() + 1.0D);
return level.getEntitiesOfClass(AbstractMinecart.class, box, cart ->
cart instanceof AntimetalMinecartAccess access && pos.equals(access.antarchy$getAntimetalRailPos()));
}
@Override
protected boolean isSignalSource(BlockState state) {
return true;
}
@Override
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return state.getValue(POWERED) ? 15 : 0;
}
@Override
protected int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return state.getValue(POWERED) ? 15 : 0;
}
@Override
protected boolean hasAnalogOutputSignal(BlockState state) {
return true;
}
@Override
protected int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos) {
if (!state.getValue(POWERED)) {
return 0;
}
int best = 0;
for (AbstractMinecart cart : getDetectedCarts(level, pos)) {
if (cart instanceof Container container) {
best = Math.max(best, AbstractContainerMenu.getRedstoneSignalFromContainer(container));
}
}
return best;
}
}
@@ -0,0 +1,80 @@
package com.craisinlord.antarchy.content.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.RailShape;
public final class AntimetalPowerHelper {
private static final int MAX_POWER_PROPAGATION = 8;
private AntimetalPowerHelper() {
}
public static boolean hasAnySignal(LevelReader level, BlockPos pos) {
if (level instanceof Level realLevel && realLevel.hasNeighborSignal(pos)) {
return true;
}
return BluestoneSignalHelper.getBestNeighborSignal(level, pos) > 0;
}
public static int getBestAnySignal(LevelReader level, BlockPos pos) {
int vanillaSignal = level instanceof Level realLevel ? realLevel.getBestNeighborSignal(pos) : 0;
int bluestoneSignal = BluestoneSignalHelper.getBestNeighborSignal(level, pos);
return Math.max(vanillaSignal, bluestoneSignal);
}
public static void notifyAllSignalNeighbors(Level level, BlockPos pos) {
level.updateNeighborsAt(pos, level.getBlockState(pos).getBlock());
BluestoneSignalHelper.updateBluestoneNeighbors(level, pos);
}
public static boolean isPoweredWithChain(Level level, BlockPos pos, BlockState state, EnumProperty<RailShape> shapeProperty, Class<? extends Block> railClass) {
if (!railClass.isInstance(state.getBlock())) {
return false;
}
if (hasAnySignal(level, pos)) {
return true;
}
RailShape shape = state.getValue(shapeProperty);
for (Direction direction : exitDirections(shape)) {
if (chain(level, pos, direction, shapeProperty, railClass, 1)) {
return true;
}
}
return false;
}
private static boolean chain(Level level, BlockPos pos, Direction direction, EnumProperty<RailShape> shapeProperty, Class<? extends Block> railClass, int distance) {
if (distance > MAX_POWER_PROPAGATION) {
return false;
}
BlockPos[] candidates = {pos.relative(direction), pos.relative(direction).above(), pos.relative(direction).below()};
for (BlockPos candidate : candidates) {
BlockState candidateState = level.getBlockState(candidate);
if (railClass.isInstance(candidateState.getBlock()) && sameAxis(candidateState.getValue(shapeProperty), direction)) {
if (hasAnySignal(level, candidate)) {
return true;
}
if (chain(level, candidate, direction, shapeProperty, railClass, distance + 1)) {
return true;
}
}
}
return false;
}
private static boolean sameAxis(RailShape shape, Direction direction) {
boolean zAxis = shape == RailShape.NORTH_SOUTH || shape == RailShape.ASCENDING_NORTH || shape == RailShape.ASCENDING_SOUTH;
return direction.getAxis() == (zAxis ? Direction.Axis.Z : Direction.Axis.X);
}
private static Direction[] exitDirections(RailShape shape) {
boolean zAxis = shape == RailShape.NORTH_SOUTH || shape == RailShape.ASCENDING_NORTH || shape == RailShape.ASCENDING_SOUTH;
return zAxis ? new Direction[]{Direction.NORTH, Direction.SOUTH} : new Direction[]{Direction.EAST, Direction.WEST};
}
}
@@ -0,0 +1,118 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
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.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.RailShape;
public class AntimetalPoweredRailBlock extends AbstractAntimetalRailBlock {
public static final MapCodec<AntimetalPoweredRailBlock> CODEC = simpleCodec(AntimetalPoweredRailBlock::new);
public static final EnumProperty<RailShape> SHAPE = BlockStateProperties.RAIL_SHAPE_STRAIGHT;
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
public AntimetalPoweredRailBlock(BlockBehaviour.Properties properties) {
super(true, properties);
this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, RailShape.NORTH_SOUTH).setValue(POWERED, false).setValue(WATERLOGGED, false));
}
@Override
protected MapCodec<? extends AbstractAntimetalRailBlock> codec() {
return CODEC;
}
@Override
public Property<RailShape> getShapeProperty() {
return SHAPE;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SHAPE, POWERED, WATERLOGGED);
}
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) {
super.neighborChanged(state, level, pos, neighborBlock, neighborPos, movedByPiston);
updatePoweredState(level, pos, level.getBlockState(pos));
}
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
super.onPlace(state, level, pos, oldState, movedByPiston);
if (!oldState.is(state.getBlock())) {
updatePoweredState(level, pos, level.getBlockState(pos));
}
}
private void updatePoweredState(Level level, BlockPos pos, BlockState state) {
if (level.isClientSide() || !(state.getBlock() instanceof AntimetalPoweredRailBlock)) {
return;
}
boolean powered = AntimetalPowerHelper.isPoweredWithChain(level, pos, state, SHAPE, AntimetalPoweredRailBlock.class);
if (state.getValue(POWERED) != powered) {
level.setBlock(pos, state.setValue(POWERED, powered), 3);
AntimetalPowerHelper.notifyAllSignalNeighbors(level, pos.below());
AntimetalPowerHelper.notifyAllSignalNeighbors(level, pos.above());
}
}
@Override
protected BlockState rotate(BlockState state, net.minecraft.world.level.block.Rotation rotation) {
return switch (rotation) {
case CLOCKWISE_180 -> switch (state.getValue(SHAPE)) {
case NORTH_SOUTH -> state.setValue(SHAPE, RailShape.NORTH_SOUTH);
case EAST_WEST -> state.setValue(SHAPE, RailShape.EAST_WEST);
case ASCENDING_EAST -> state.setValue(SHAPE, RailShape.ASCENDING_WEST);
case ASCENDING_WEST -> state.setValue(SHAPE, RailShape.ASCENDING_EAST);
case ASCENDING_NORTH -> state.setValue(SHAPE, RailShape.ASCENDING_SOUTH);
case ASCENDING_SOUTH -> state.setValue(SHAPE, RailShape.ASCENDING_NORTH);
default -> state;
};
case CLOCKWISE_90 -> switch (state.getValue(SHAPE)) {
case NORTH_SOUTH -> state.setValue(SHAPE, RailShape.EAST_WEST);
case EAST_WEST -> state.setValue(SHAPE, RailShape.NORTH_SOUTH);
case ASCENDING_EAST -> state.setValue(SHAPE, RailShape.ASCENDING_NORTH);
case ASCENDING_WEST -> state.setValue(SHAPE, RailShape.ASCENDING_SOUTH);
case ASCENDING_NORTH -> state.setValue(SHAPE, RailShape.ASCENDING_WEST);
case ASCENDING_SOUTH -> state.setValue(SHAPE, RailShape.ASCENDING_EAST);
default -> state;
};
case COUNTERCLOCKWISE_90 -> switch (state.getValue(SHAPE)) {
case NORTH_SOUTH -> state.setValue(SHAPE, RailShape.EAST_WEST);
case EAST_WEST -> state.setValue(SHAPE, RailShape.NORTH_SOUTH);
case ASCENDING_EAST -> state.setValue(SHAPE, RailShape.ASCENDING_SOUTH);
case ASCENDING_WEST -> state.setValue(SHAPE, RailShape.ASCENDING_NORTH);
case ASCENDING_NORTH -> state.setValue(SHAPE, RailShape.ASCENDING_EAST);
case ASCENDING_SOUTH -> state.setValue(SHAPE, RailShape.ASCENDING_WEST);
default -> state;
};
default -> state;
};
}
@Override
protected BlockState mirror(BlockState state, net.minecraft.world.level.block.Mirror mirror) {
RailShape shape = state.getValue(SHAPE);
return switch (mirror) {
case LEFT_RIGHT -> switch (shape) {
case ASCENDING_NORTH -> state.setValue(SHAPE, RailShape.ASCENDING_SOUTH);
case ASCENDING_SOUTH -> state.setValue(SHAPE, RailShape.ASCENDING_NORTH);
default -> state;
};
case FRONT_BACK -> switch (shape) {
case ASCENDING_EAST -> state.setValue(SHAPE, RailShape.ASCENDING_WEST);
case ASCENDING_WEST -> state.setValue(SHAPE, RailShape.ASCENDING_EAST);
default -> state;
};
default -> state;
};
}
}
@@ -0,0 +1,34 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.world.level.block.state.BlockBehaviour;
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.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.RailShape;
public class AntimetalRailBlock extends AbstractAntimetalRailBlock {
public static final MapCodec<AntimetalRailBlock> CODEC = simpleCodec(AntimetalRailBlock::new);
public static final EnumProperty<RailShape> SHAPE = BlockStateProperties.RAIL_SHAPE;
public AntimetalRailBlock(BlockBehaviour.Properties properties) {
super(false, properties);
this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, RailShape.NORTH_SOUTH).setValue(WATERLOGGED, false));
}
@Override
protected MapCodec<? extends AbstractAntimetalRailBlock> codec() {
return CODEC;
}
@Override
public Property<RailShape> getShapeProperty() {
return SHAPE;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<net.minecraft.world.level.block.Block, net.minecraft.world.level.block.state.BlockState> builder) {
builder.add(SHAPE, WATERLOGGED);
}
}
@@ -6,19 +6,30 @@ import java.util.function.Supplier;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.SignalGetter;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ComparatorBlock; import net.minecraft.world.level.block.ComparatorBlock;
import net.minecraft.world.level.block.DiodeBlock;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.ComparatorMode;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.ticks.TickPriority;
import org.joml.Vector3f; import org.joml.Vector3f;
public class BluestoneComparatorBlock extends ComparatorBlock { public class BluestoneComparatorBlock extends ComparatorBlock {
@@ -58,7 +69,7 @@ public class BluestoneComparatorBlock extends ComparatorBlock {
@Override @Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (!state.canSurvive(level, pos)) { if (direction == Direction.UP && !state.canSurvive(level, pos)) {
return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState();
} }
return super.updateShape(state, direction, neighborState, level, pos, neighborPos); return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
@@ -69,6 +80,122 @@ public class BluestoneComparatorBlock extends ComparatorBlock {
return new BluestoneComparatorBlockEntity(pos, state, this.blockEntityTypeSupplier); return new BluestoneComparatorBlockEntity(pos, state, this.blockEntityTypeSupplier);
} }
@Override
protected int getOutputSignal(BlockGetter level, BlockPos pos, BlockState state) {
BlockEntity blockEntity = level.getBlockEntity(pos);
return blockEntity instanceof BluestoneComparatorBlockEntity comparator ? comparator.getOutputSignal() : 0;
}
@Override
protected int getInputSignal(Level level, BlockPos pos, BlockState state) {
Direction facing = state.getValue(FACING);
BlockPos inputPos = pos.relative(facing);
BlockState inputState = level.getBlockState(inputPos);
int signal = BluestoneSignalHelper.getSignalExcludingRedstoneWire(level, inputPos, facing);
signal = Math.max(signal, this.getDirectBluestoneRearSignal(level, inputPos, inputState, facing));
if (signal < 15 && inputState.isRedstoneConductor(level, inputPos)) {
BlockPos fartherInputPos = inputPos.relative(facing);
BlockState fartherInputState = level.getBlockState(fartherInputPos);
signal = Math.max(signal, BluestoneSignalHelper.getSignalExcludingRedstoneWire(level, fartherInputPos, facing));
signal = Math.max(signal, this.getDirectBluestoneRearSignal(level, fartherInputPos, fartherInputState, facing));
}
return signal;
}
@Override
protected int getAlternateSignal(SignalGetter level, BlockPos pos, BlockState state) {
Direction facing = state.getValue(FACING);
Direction clockwise = facing.getClockWise();
Direction counterClockwise = facing.getCounterClockWise();
int signal = this.getBluestoneSideSignal(level, pos.relative(clockwise), clockwise.getOpposite());
signal = Math.max(signal, this.getBluestoneSideSignal(level, pos.relative(counterClockwise), counterClockwise.getOpposite()));
return signal;
}
private int getBluestoneSideSignal(SignalGetter level, BlockPos pos, Direction direction) {
BlockState neighborState = level.getBlockState(pos);
if (neighborState.getBlock() instanceof BluestoneSignalSource source) {
return source.getBluestoneSignal(level instanceof LevelReader levelReader ? levelReader : null, pos, neighborState, direction);
}
return 0;
}
private int getDirectBluestoneRearSignal(LevelReader level, BlockPos pos, BlockState state, Direction direction) {
if (state.getBlock() instanceof BluestoneSignalSource source) {
return source.getBluestoneSignal(level, pos, state, direction);
}
return BluestoneSignalHelper.getDirectBluestoneSignal(level, pos, direction);
}
@Override
protected boolean isSignalSource(BlockState state) {
return true;
}
@Override
protected void checkTickOnNeighbor(Level level, BlockPos pos, BlockState state) {
if (level.getBlockTicks().willTickThisTick(pos, this)) {
return;
}
int outputSignal = this.calculateBluestoneOutputSignal(level, pos, state);
int storedOutputSignal = this.getOutputSignal(level, pos, state);
if (outputSignal != storedOutputSignal || state.getValue(POWERED) != this.shouldTurnOn(level, pos, state)) {
TickPriority tickPriority = this.shouldPrioritize(level, pos, state) ? TickPriority.HIGH : TickPriority.NORMAL;
level.scheduleTick(pos, this, 2, tickPriority);
}
}
@Override
protected void tick(BlockState state, net.minecraft.server.level.ServerLevel level, BlockPos pos, RandomSource random) {
this.refreshBluestoneOutputState(level, pos, state);
}
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (!player.getAbilities().mayBuild) {
return InteractionResult.PASS;
}
BlockState updated = state.cycle(MODE);
float pitch = updated.getValue(MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F;
level.playSound(player, pos, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3F, pitch);
level.setBlock(pos, updated, 2);
this.refreshBluestoneOutputState(level, pos, updated);
return InteractionResult.sidedSuccess(level.isClientSide);
}
private int calculateBluestoneOutputSignal(Level level, BlockPos pos, BlockState state) {
int inputSignal = this.getInputSignal(level, pos, state);
if (inputSignal == 0) {
return 0;
}
int alternateSignal = this.getAlternateSignal(level, pos, state);
if (alternateSignal > inputSignal) {
return 0;
}
return state.getValue(MODE) == ComparatorMode.SUBTRACT ? inputSignal - alternateSignal : inputSignal;
}
private void refreshBluestoneOutputState(Level level, BlockPos pos, BlockState state) {
int outputSignal = this.calculateBluestoneOutputSignal(level, pos, state);
BlockEntity blockEntity = level.getBlockEntity(pos);
int storedOutputSignal = 0;
if (blockEntity instanceof BluestoneComparatorBlockEntity comparator) {
storedOutputSignal = comparator.getOutputSignal();
comparator.setOutputSignal(outputSignal);
}
boolean shouldTurnOn = this.shouldTurnOn(level, pos, state);
boolean powered = state.getValue(DiodeBlock.POWERED);
if (powered != shouldTurnOn) {
state = state.setValue(DiodeBlock.POWERED, shouldTurnOn);
level.setBlock(pos, state, 2);
}
if (storedOutputSignal != outputSignal || powered != shouldTurnOn) {
this.updateNeighborsInFront(level, pos, state);
}
}
@Override @Override
public void animateTick(BlockState state, net.minecraft.world.level.Level level, BlockPos pos, RandomSource random) { public void animateTick(BlockState state, net.minecraft.world.level.Level level, BlockPos pos, RandomSource random) {
if (!state.getValue(POWERED)) { if (!state.getValue(POWERED)) {
@@ -6,9 +6,12 @@ import net.minecraft.core.Direction;
import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.SignalGetter;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RepeaterBlock; import net.minecraft.world.level.block.RepeaterBlock;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@@ -54,6 +57,51 @@ public class BluestoneRepeaterBlock extends RepeaterBlock {
return super.updateShape(state, direction, neighborState, level, pos, neighborPos); return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
} }
@Override
protected int getAlternateSignal(SignalGetter level, BlockPos pos, BlockState state) {
Direction facing = state.getValue(FACING);
Direction clockwise = facing.getClockWise();
Direction counterClockwise = facing.getCounterClockWise();
int signal = this.getBluestoneSideSignal(level, pos.relative(clockwise), clockwise.getOpposite());
signal = Math.max(signal, this.getBluestoneSideSignal(level, pos.relative(counterClockwise), counterClockwise.getOpposite()));
return signal;
}
@Override
protected int getInputSignal(Level level, BlockPos pos, BlockState state) {
Direction facing = state.getValue(FACING);
BlockPos inputPos = pos.relative(facing);
BlockState inputState = level.getBlockState(inputPos);
int signal = BluestoneSignalHelper.getSignalExcludingRedstoneWire(level, inputPos, facing);
if (signal >= 15) {
return signal;
}
if (inputState.getBlock() instanceof BluestoneSignalSource source) {
return Math.max(signal, source.getBluestoneSignal(level, inputPos, inputState, facing));
}
return signal;
}
@Override
public boolean isLocked(LevelReader level, BlockPos pos, BlockState state) {
return this.getAlternateSignal(level, pos, state) > 0;
}
private int getBluestoneSideSignal(SignalGetter level, BlockPos pos, Direction towardThisRepeater) {
BlockState neighborState = level.getBlockState(pos);
if (neighborState.getBlock() instanceof BluestoneRepeaterBlock
&& neighborState.getValue(POWERED)
&& neighborState.getValue(FACING) == towardThisRepeater) {
return 15;
}
return 0;
}
@Override
protected boolean isSignalSource(BlockState state) {
return true;
}
@Override @Override
public void animateTick(BlockState state, net.minecraft.world.level.Level level, BlockPos pos, RandomSource random) { public void animateTick(BlockState state, net.minecraft.world.level.Level level, BlockPos pos, RandomSource random) {
if (!state.getValue(POWERED)) { if (!state.getValue(POWERED)) {
@@ -4,7 +4,9 @@ import com.craisinlord.antarchy.content.AntarchyTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
public final class BluestoneSignalHelper { public final class BluestoneSignalHelper {
@@ -38,6 +40,34 @@ public final class BluestoneSignalHelper {
return 0; return 0;
} }
public static int getSignalExcludingRedstoneWire(LevelReader level, BlockPos pos, Direction direction) {
BlockState state = level.getBlockState(pos);
if (state.is(Blocks.REDSTONE_WIRE)) {
return 0;
}
int signal = state.getSignal(level, pos, direction);
if (state.isRedstoneConductor(level, pos)) {
signal = Math.max(signal, getDirectSignalToExcludingRedstoneWire(level, pos));
}
return signal;
}
private static int getDirectSignalToExcludingRedstoneWire(BlockGetter level, BlockPos pos) {
int signal = 0;
for (Direction direction : Direction.values()) {
BlockPos neighborPos = pos.relative(direction);
BlockState neighborState = level.getBlockState(neighborPos);
if (neighborState.is(Blocks.REDSTONE_WIRE)) {
continue;
}
signal = Math.max(signal, neighborState.getDirectSignal(level, neighborPos, direction));
if (signal >= 15) {
return 15;
}
}
return signal;
}
public static boolean canBluestoneConnectTo(BlockState state) { public static boolean canBluestoneConnectTo(BlockState state) {
return state.is(AntarchyTags.Blocks.BLUESTONE_CONNECTABLE); return state.is(AntarchyTags.Blocks.BLUESTONE_CONNECTABLE);
} }
@@ -16,29 +16,83 @@ import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.AttachFace;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import org.joml.Vector3f; import org.joml.Vector3f;
public class BluestoneTorchBlock extends AbstractCeilingBluestoneBlock implements BluestoneSignalSource { public class BluestoneTorchBlock extends Block implements BluestoneSignalSource {
public static final BooleanProperty LIT = BlockStateProperties.LIT; public static final BooleanProperty LIT = BlockStateProperties.LIT;
private static final VoxelShape SHAPE = Block.box(6.0D, 6.0D, 6.0D, 10.0D, 16.0D, 10.0D); public static final EnumProperty<AttachFace> FACE = BlockStateProperties.ATTACH_FACE;
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
private static final VoxelShape CEILING_SHAPE = Block.box(6.0D, 6.0D, 6.0D, 10.0D, 16.0D, 10.0D);
private static final Map<Direction, VoxelShape> WALL_SHAPES = Map.of(
Direction.NORTH, Block.box(5.5D, 3.0D, 11.0D, 10.5D, 13.0D, 16.0D),
Direction.SOUTH, Block.box(5.5D, 3.0D, 0.0D, 10.5D, 13.0D, 5.0D),
Direction.WEST, Block.box(11.0D, 3.0D, 5.5D, 16.0D, 13.0D, 10.5D),
Direction.EAST, Block.box(0.0D, 3.0D, 5.5D, 5.0D, 13.0D, 10.5D)
);
private static final DustParticleOptions BLUESTONE_PARTICLE = new DustParticleOptions(new Vector3f(0.18F, 0.54F, 1.0F), 1.0F); private static final DustParticleOptions BLUESTONE_PARTICLE = new DustParticleOptions(new Vector3f(0.18F, 0.54F, 1.0F), 1.0F);
private static final Map<Level, List<Toggle>> RECENT_TOGGLES = new WeakHashMap<>(); private static final Map<Level, List<Toggle>> RECENT_TOGGLES = new WeakHashMap<>();
public BluestoneTorchBlock(BlockBehaviour.Properties properties) { public BluestoneTorchBlock(BlockBehaviour.Properties properties) {
super(properties); super(properties);
this.registerDefaultState(this.defaultBlockState().setValue(LIT, true)); this.registerDefaultState(this.defaultBlockState()
.setValue(LIT, true)
.setValue(FACE, AttachFace.CEILING)
.setValue(FACING, Direction.NORTH));
} }
@Override @Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return SHAPE; return state.getValue(FACE) == AttachFace.WALL ? WALL_SHAPES.get(state.getValue(FACING)) : CEILING_SHAPE;
}
@Override
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
return switch (state.getValue(FACE)) {
case CEILING -> BluestonePlacementHelper.hasCeilingSupport(level, pos);
case WALL -> this.hasWallSupport(level, pos, state.getValue(FACING));
default -> false;
};
}
@Override
public BlockState getStateForPlacement(net.minecraft.world.item.context.BlockPlaceContext context) {
LevelReader level = context.getLevel();
BlockPos pos = context.getClickedPos();
for (Direction direction : context.getNearestLookingDirections()) {
if (direction == Direction.DOWN && BluestonePlacementHelper.hasCeilingSupport(level, pos)) {
return this.defaultBlockState().setValue(FACE, AttachFace.CEILING);
}
if (direction.getAxis().isHorizontal()) {
Direction facing = direction.getOpposite();
BlockState state = this.defaultBlockState().setValue(FACE, AttachFace.WALL).setValue(FACING, facing);
if (state.canSurvive(level, pos)) {
return state;
}
}
}
return null;
}
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, net.minecraft.world.level.LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (!state.canSurvive(level, pos)) {
return net.minecraft.world.level.block.Blocks.AIR.defaultBlockState();
}
return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
} }
@Override @Override
@@ -48,7 +102,10 @@ public class BluestoneTorchBlock extends AbstractCeilingBluestoneBlock implement
@Override @Override
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
if (direction == Direction.DOWN) { if (this.isDirectlyPoweringRedstoneWire(level, pos, direction)) {
return 0;
}
if (this.isBlockedOutputDirection(state, direction)) {
return 0; return 0;
} }
return state.getValue(LIT) ? 15 : 0; return state.getValue(LIT) ? 15 : 0;
@@ -56,7 +113,16 @@ public class BluestoneTorchBlock extends AbstractCeilingBluestoneBlock implement
@Override @Override
protected int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { protected int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return this.getSignal(state, level, pos, direction); if (!state.getValue(LIT)) {
return 0;
}
if (this.isDirectlyPoweringRedstoneWire(level, pos, direction)) {
return 0;
}
if (state.getValue(FACE) == AttachFace.WALL) {
return direction == Direction.UP ? 15 : 0;
}
return this.isBlockedOutputDirection(state, direction) ? 0 : 15;
} }
@Override @Override
@@ -76,7 +142,7 @@ public class BluestoneTorchBlock extends AbstractCeilingBluestoneBlock implement
@Override @Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean moving) { protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean moving) {
if (!level.isClientSide) { if (!level.isClientSide) {
boolean powered = this.hasInputSignal(level, pos); boolean powered = this.hasInputSignal(level, pos, state);
if (state.getValue(LIT) == powered) { if (state.getValue(LIT) == powered) {
level.scheduleTick(pos, this, 2); level.scheduleTick(pos, this, 2);
} }
@@ -85,7 +151,7 @@ public class BluestoneTorchBlock extends AbstractCeilingBluestoneBlock implement
@Override @Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
boolean powered = this.hasInputSignal(level, pos); boolean powered = this.hasInputSignal(level, pos, state);
boolean lit = state.getValue(LIT); boolean lit = state.getValue(LIT);
if (lit) { if (lit) {
@@ -108,24 +174,57 @@ public class BluestoneTorchBlock extends AbstractCeilingBluestoneBlock implement
return; return;
} }
double x = pos.getX() + 0.5D; double x = pos.getX() + 0.5D;
double y = pos.getY() + 0.3D; double y = pos.getY() + (state.getValue(FACE) == AttachFace.CEILING ? 0.3D : 0.35D);
double z = pos.getZ() + 0.5D; double z = pos.getZ() + 0.5D;
if (state.getValue(FACE) == AttachFace.WALL) {
Direction facing = state.getValue(FACING).getOpposite();
x += 0.27D * facing.getStepX();
z += 0.27D * facing.getStepZ();
}
level.addParticle(ParticleTypes.SMOKE, x, y, z, 0.0D, 0.0D, 0.0D); level.addParticle(ParticleTypes.SMOKE, x, y, z, 0.0D, 0.0D, 0.0D);
level.addParticle(BLUESTONE_PARTICLE, x, y, z, 0.0D, 0.0D, 0.0D); level.addParticle(BLUESTONE_PARTICLE, x, y, z, 0.0D, 0.0D, 0.0D);
} }
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(LIT); builder.add(LIT, FACE, FACING);
} }
@Override @Override
public int getBluestoneSignal(LevelReader level, BlockPos pos, BlockState state, Direction direction) { public int getBluestoneSignal(LevelReader level, BlockPos pos, BlockState state, Direction direction) {
return direction == Direction.DOWN ? 0 : state.getValue(LIT) ? 15 : 0; return this.isBlockedOutputDirection(state, direction) ? 0 : state.getValue(LIT) ? 15 : 0;
} }
private boolean hasInputSignal(Level level, BlockPos pos) { @Override
return level.hasNeighborSignal(pos.above()); protected BlockState rotate(BlockState state, Rotation rotation) {
return state.getValue(FACE) == AttachFace.WALL ? state.setValue(FACING, rotation.rotate(state.getValue(FACING))) : state;
}
@Override
protected BlockState mirror(BlockState state, Mirror mirror) {
return state.getValue(FACE) == AttachFace.WALL ? state.rotate(mirror.getRotation(state.getValue(FACING))) : state;
}
private boolean hasInputSignal(Level level, BlockPos pos, BlockState state) {
Direction supportDirection = state.getValue(FACE) == AttachFace.CEILING ? Direction.UP : state.getValue(FACING).getOpposite();
return level.hasSignal(pos.relative(supportDirection), supportDirection);
}
private boolean hasWallSupport(LevelReader level, BlockPos pos, Direction facing) {
BlockPos supportPos = pos.relative(facing.getOpposite());
return level.getBlockState(supportPos).isFaceSturdy(level, supportPos, facing);
}
private boolean isBlockedOutputDirection(BlockState state, Direction direction) {
return this.getBlockedOutputDirection(state) == direction;
}
private boolean isDirectlyPoweringRedstoneWire(BlockGetter level, BlockPos pos, Direction direction) {
return level.getBlockState(pos.relative(direction.getOpposite())).is(Blocks.REDSTONE_WIRE);
}
private Direction getBlockedOutputDirection(BlockState state) {
return state.getValue(FACE) == AttachFace.WALL ? state.getValue(FACING) : Direction.DOWN;
} }
private boolean isToggledTooFrequently(Level level, BlockPos pos, boolean addNew) { private boolean isToggledTooFrequently(Level level, BlockPos pos, boolean addNew) {
@@ -10,6 +10,9 @@ import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
@@ -17,8 +20,10 @@ import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock; import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.TrapDoorBlock;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
@@ -48,6 +53,7 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
private static final VoxelShape WEST_SHAPE = Block.box(0.0D, 14.0D, 3.0D, 13.0D, 16.0D, 13.0D); private static final VoxelShape WEST_SHAPE = Block.box(0.0D, 14.0D, 3.0D, 13.0D, 16.0D, 13.0D);
private static final VoxelShape EAST_SHAPE = Block.box(3.0D, 14.0D, 3.0D, 16.0D, 16.0D, 13.0D); private static final VoxelShape EAST_SHAPE = Block.box(3.0D, 14.0D, 3.0D, 16.0D, 16.0D, 13.0D);
private static boolean shouldSignal = true; private static boolean shouldSignal = true;
private final BlockState crossState;
public BluestoneWireBlock() { public BluestoneWireBlock() {
this(BlockBehaviour.Properties.of().noCollission().instabreak().sound(SoundType.WOOL)); this(BlockBehaviour.Properties.of().noCollission().instabreak().sound(SoundType.WOOL));
@@ -55,12 +61,18 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
public BluestoneWireBlock(BlockBehaviour.Properties properties) { public BluestoneWireBlock(BlockBehaviour.Properties properties) {
super(properties); super(properties);
this.registerDefaultState(this.defaultBlockState() BlockState defaultState = this.defaultBlockState()
.setValue(NORTH, BluestoneSide.NONE) .setValue(NORTH, BluestoneSide.NONE)
.setValue(EAST, BluestoneSide.NONE) .setValue(EAST, BluestoneSide.NONE)
.setValue(SOUTH, BluestoneSide.NONE) .setValue(SOUTH, BluestoneSide.NONE)
.setValue(WEST, BluestoneSide.NONE) .setValue(WEST, BluestoneSide.NONE)
.setValue(POWER, 0)); .setValue(POWER, 0);
this.registerDefaultState(defaultState);
this.crossState = defaultState
.setValue(NORTH, BluestoneSide.SIDE)
.setValue(EAST, BluestoneSide.SIDE)
.setValue(SOUTH, BluestoneSide.SIDE)
.setValue(WEST, BluestoneSide.SIDE);
} }
public MapCodec<BluestoneWireBlock> codec() { public MapCodec<BluestoneWireBlock> codec() {
@@ -117,6 +129,7 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
@Override @Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean moving) { protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean moving) {
if (!oldState.is(state.getBlock())) { if (!oldState.is(state.getBlock())) {
this.notifyNeighborShapes(level, pos);
this.updateNeighbors(level, pos, state); this.updateNeighbors(level, pos, state);
} }
} }
@@ -124,13 +137,11 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
@Override @Override
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
if (!state.is(newState.getBlock())) { if (!state.is(newState.getBlock())) {
BluestoneSignalHelper.updateBluestoneNeighbors(level, pos); this.notifyNeighborShapes(level, pos);
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos neighborPos = pos.relative(direction); this.updateNeighborWire(level, pos.relative(direction));
BlockState neighborState = level.getBlockState(neighborPos); this.updateNeighborWire(level, pos.relative(direction).above());
if (neighborState.is(this)) { this.updateNeighborWire(level, pos.relative(direction).below());
this.updateNeighbors(level, neighborPos, neighborState);
}
} }
} }
super.onRemove(state, level, pos, newState, movedByPiston); super.onRemove(state, level, pos, newState, movedByPiston);
@@ -169,23 +180,33 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
@Override @Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (level.isClientSide) { if (!player.getAbilities().mayBuild) {
return InteractionResult.PASS;
}
if (!isCross(state) && !isDot(state)) {
return InteractionResult.PASS;
}
BlockState toggled = isCross(state) ? this.defaultBlockState() : this.crossState;
BlockState updated = toggled.setValue(POWER, state.getValue(POWER));
if (!hasAnyAutomaticConnections(level, pos)) {
if (!updated.equals(state)) {
level.setBlock(pos, updated, 3);
}
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
boolean isDot = state.getValue(NORTH) == BluestoneSide.NONE updated = this.calculateShape(level, pos, updated);
&& state.getValue(EAST) == BluestoneSide.NONE if (!updated.equals(state)) {
&& state.getValue(SOUTH) == BluestoneSide.NONE
&& state.getValue(WEST) == BluestoneSide.NONE;
BlockState updated = isDot
? this.calculateShape(level, pos, state)
: state.setValue(NORTH, BluestoneSide.NONE)
.setValue(EAST, BluestoneSide.NONE)
.setValue(SOUTH, BluestoneSide.NONE)
.setValue(WEST, BluestoneSide.NONE);
level.setBlock(pos, updated, 3); level.setBlock(pos, updated, 3);
this.updateNeighbors(level, pos, updated); this.updateNeighbors(level, pos, updated);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
return InteractionResult.PASS;
}
@Override
public ItemStack getCloneItemStack(LevelReader level, BlockPos pos, BlockState state) {
return new ItemStack(BuiltInRegistries.ITEM.get(ResourceLocation.fromNamespaceAndPath("antarchy", "bluestone")));
}
@Override @Override
protected BlockState rotate(BlockState state, Rotation rotation) { protected BlockState rotate(BlockState state, Rotation rotation) {
@@ -235,10 +256,37 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
} }
BlockState shaped = this.calculateShape(level, pos, state); BlockState shaped = this.calculateShape(level, pos, state);
BlockState powered = this.updatePowerFromNeighbors(level, pos, shaped); BlockState powered = this.updatePowerFromNeighbors(level, pos, shaped);
if (!powered.equals(state)) { if (powered.equals(state)) {
level.setBlock(pos, powered, 3); return;
}
level.setBlock(pos, powered, 2);
this.notifyNeighborShapes(level, pos);
for (Direction direction : Direction.Plane.HORIZONTAL) {
this.updateNeighborWire(level, pos.relative(direction));
this.updateNeighborWire(level, pos.relative(direction).above());
this.updateNeighborWire(level, pos.relative(direction).below());
}
}
private void updateNeighborWire(Level level, BlockPos pos) {
BlockState neighborState = level.getBlockState(pos);
if (!neighborState.is(this)) {
return;
}
BlockState shaped = this.calculateShape(level, pos, neighborState);
BlockState powered = this.updatePowerFromNeighbors(level, pos, shaped);
if (powered.equals(neighborState)) {
return;
}
level.setBlock(pos, powered, 2);
this.notifyNeighborShapes(level, pos);
}
private void notifyNeighborShapes(Level level, BlockPos pos) {
level.updateNeighborsAt(pos, this);
for (Direction direction : Direction.values()) {
level.updateNeighborsAt(pos.relative(direction), this);
} }
BluestoneSignalHelper.updateBluestoneNeighbors(level, pos);
} }
private BlockState updatePowerFromNeighbors(Level level, BlockPos pos, BlockState state) { private BlockState updatePowerFromNeighbors(Level level, BlockPos pos, BlockState state) {
@@ -249,12 +297,15 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
private int calculateTargetStrength(Level level, BlockPos pos) { private int calculateTargetStrength(Level level, BlockPos pos) {
int external = this.getExternalSignal(level, pos); int external = this.getExternalSignal(level, pos);
int neighborWirePower = 0; int neighborWirePower = 0;
boolean openBelowCurrent = !level.getBlockState(pos.below()).isRedstoneConductor(level, pos.below());
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos sidePos = pos.relative(direction); BlockPos sidePos = pos.relative(direction);
BlockState sideState = level.getBlockState(sidePos);
neighborWirePower = Math.max(neighborWirePower, BluestoneSignalHelper.getWireSignal(level, sidePos)); neighborWirePower = Math.max(neighborWirePower, BluestoneSignalHelper.getWireSignal(level, sidePos));
if (sideState.isRedstoneConductor(level, sidePos)) {
neighborWirePower = Math.max(neighborWirePower, BluestoneSignalHelper.getWireSignal(level, sidePos.below())); neighborWirePower = Math.max(neighborWirePower, BluestoneSignalHelper.getWireSignal(level, sidePos.below()));
if (level.getBlockState(sidePos).isRedstoneConductor(level, sidePos)) { } else if (openBelowCurrent) {
neighborWirePower = Math.max(neighborWirePower, BluestoneSignalHelper.getWireSignal(level, sidePos.above())); neighborWirePower = Math.max(neighborWirePower, BluestoneSignalHelper.getWireSignal(level, sidePos.above()));
} }
} }
@@ -281,32 +332,90 @@ public class BluestoneWireBlock extends Block implements BluestoneSignalSource {
return signal; return signal;
} }
private static boolean isCross(BlockState state) {
return state.getValue(NORTH) != BluestoneSide.NONE
&& state.getValue(EAST) != BluestoneSide.NONE
&& state.getValue(SOUTH) != BluestoneSide.NONE
&& state.getValue(WEST) != BluestoneSide.NONE;
}
private static boolean isDot(BlockState state) {
return state.getValue(NORTH) == BluestoneSide.NONE
&& state.getValue(EAST) == BluestoneSide.NONE
&& state.getValue(SOUTH) == BluestoneSide.NONE
&& state.getValue(WEST) == BluestoneSide.NONE;
}
private boolean hasAnyAutomaticConnections(LevelReader level, BlockPos pos) {
return this.getConnectingSide(level, pos, Direction.NORTH) != BluestoneSide.NONE
|| this.getConnectingSide(level, pos, Direction.EAST) != BluestoneSide.NONE
|| this.getConnectingSide(level, pos, Direction.SOUTH) != BluestoneSide.NONE
|| this.getConnectingSide(level, pos, Direction.WEST) != BluestoneSide.NONE;
}
private BlockState calculateShape(LevelReader level, BlockPos pos, BlockState state) { private BlockState calculateShape(LevelReader level, BlockPos pos, BlockState state) {
return state.setValue(NORTH, this.getConnectingSide(level, pos, Direction.NORTH)) boolean wasDot = isDot(state);
BlockState result = state.setValue(NORTH, this.getConnectingSide(level, pos, Direction.NORTH))
.setValue(EAST, this.getConnectingSide(level, pos, Direction.EAST)) .setValue(EAST, this.getConnectingSide(level, pos, Direction.EAST))
.setValue(SOUTH, this.getConnectingSide(level, pos, Direction.SOUTH)) .setValue(SOUTH, this.getConnectingSide(level, pos, Direction.SOUTH))
.setValue(WEST, this.getConnectingSide(level, pos, Direction.WEST)); .setValue(WEST, this.getConnectingSide(level, pos, Direction.WEST));
if (wasDot && isDot(result)) {
return result;
}
boolean north = result.getValue(NORTH) != BluestoneSide.NONE;
boolean south = result.getValue(SOUTH) != BluestoneSide.NONE;
boolean east = result.getValue(EAST) != BluestoneSide.NONE;
boolean west = result.getValue(WEST) != BluestoneSide.NONE;
boolean northSouthEmpty = !north && !south;
boolean eastWestEmpty = !east && !west;
if (!west && northSouthEmpty) {
result = result.setValue(WEST, BluestoneSide.SIDE);
}
if (!east && northSouthEmpty) {
result = result.setValue(EAST, BluestoneSide.SIDE);
}
if (!north && eastWestEmpty) {
result = result.setValue(NORTH, BluestoneSide.SIDE);
}
if (!south && eastWestEmpty) {
result = result.setValue(SOUTH, BluestoneSide.SIDE);
}
return result;
} }
private BluestoneSide getConnectingSide(LevelReader level, BlockPos pos, Direction direction) { private BluestoneSide getConnectingSide(LevelReader level, BlockPos pos, Direction direction) {
boolean openBelowCurrent = !level.getBlockState(pos.below()).isRedstoneConductor(level, pos.below());
return this.getConnectingSide(level, pos, direction, openBelowCurrent);
}
private BluestoneSide getConnectingSide(LevelReader level, BlockPos pos, Direction direction, boolean openBelowCurrent) {
BlockPos sidePos = pos.relative(direction); BlockPos sidePos = pos.relative(direction);
BlockState sideState = level.getBlockState(sidePos); BlockState sideState = level.getBlockState(sidePos);
if (openBelowCurrent) {
boolean canSupportBelow = sideState.getBlock() instanceof TrapDoorBlock
|| Block.canSupportCenter(level, sidePos, Direction.DOWN);
if (canSupportBelow && this.canConnectTo(level.getBlockState(sidePos.below()), direction)) {
return sideState.isFaceSturdy(level, sidePos, direction.getOpposite()) ? BluestoneSide.DOWN : BluestoneSide.SIDE;
}
}
if (this.canConnectTo(sideState, direction)) { if (this.canConnectTo(sideState, direction)) {
return BluestoneSide.SIDE; return BluestoneSide.SIDE;
} }
if (!sideState.isRedstoneConductor(level, sidePos) && this.canConnectTo(level.getBlockState(sidePos.below()), direction)) { if (sideState.isRedstoneConductor(level, sidePos)) {
return BluestoneSide.DOWN;
}
if (sideState.isRedstoneConductor(level, sidePos) && this.canConnectTo(level.getBlockState(sidePos.above()), direction)) {
return BluestoneSide.SIDE;
}
return BluestoneSide.NONE; return BluestoneSide.NONE;
} }
BlockPos sidePosAbove = sidePos.above();
return this.canConnectTo(level.getBlockState(sidePosAbove), direction) ? BluestoneSide.SIDE : BluestoneSide.NONE;
}
private boolean canConnectTo(BlockState state, Direction direction) { private boolean canConnectTo(BlockState state, Direction direction) {
if (state.getBlock() instanceof RedStoneWireBlock || state.is(net.minecraft.world.level.block.Blocks.REDSTONE_WIRE)) {
return false;
}
if (state.getBlock() instanceof BluestoneWireBlock || state.getBlock() instanceof BluestoneTorchBlock || state.getBlock() instanceof BluestoneBlock) { if (state.getBlock() instanceof BluestoneWireBlock || state.getBlock() instanceof BluestoneTorchBlock || state.getBlock() instanceof BluestoneBlock) {
return true; return true;
} }
@@ -8,6 +8,8 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.BlockTags; import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -147,6 +149,7 @@ public class CorneaStalkBlock extends BushBlock implements BonemealableBlock {
if (!level.isClientSide) { if (!level.isClientSide) {
this.dropCorneaFruit(level, pos, level.random); this.dropCorneaFruit(level, pos, level.random);
level.setBlock(pos, state.setValue(AGE, 1), Block.UPDATE_ALL); level.setBlock(pos, state.setValue(AGE, 1), Block.UPDATE_ALL);
level.playSound(null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.9F + level.random.nextFloat() * 0.2F);
} }
return ItemInteractionResult.sidedSuccess(level.isClientSide); return ItemInteractionResult.sidedSuccess(level.isClientSide);
@@ -0,0 +1,73 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.VineBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
public class CreepvineBlock extends VineBlock {
public static final MapCodec<CreepvineBlock> CODEC = Block.simpleCodec(CreepvineBlock::new);
public static final BooleanProperty STUNTED = BooleanProperty.create("stunted");
public CreepvineBlock(BlockBehaviour.Properties properties) {
super(properties);
this.registerDefaultState(this.defaultBlockState()
.setValue(NORTH, false)
.setValue(EAST, false)
.setValue(SOUTH, false)
.setValue(WEST, false)
.setValue(UP, false)
.setValue(STUNTED, false));
}
@Override
public MapCodec<VineBlock> codec() {
return (MapCodec<VineBlock>) (MapCodec<?>) CODEC;
}
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (state.getValue(STUNTED)) {
return;
}
super.randomTick(state, level, pos, random);
}
@Override
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) {
if (!stack.is(Items.SHEARS) || state.getValue(STUNTED)) {
return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
}
if (!level.isClientSide) {
level.setBlock(pos, state.setValue(STUNTED, true), Block.UPDATE_ALL);
stack.hurtAndBreak(1, player, hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND);
level.playSound(null, pos, SoundEvents.SHEEP_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
}
return ItemInteractionResult.sidedSuccess(level.isClientSide);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(STUNTED);
}
}
@@ -3,8 +3,17 @@ package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
@@ -15,6 +24,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
@@ -22,12 +32,13 @@ public class HangingCreeprootsBlock extends BushBlock {
public static final MapCodec<HangingCreeprootsBlock> CODEC = Block.simpleCodec(HangingCreeprootsBlock::new); public static final MapCodec<HangingCreeprootsBlock> CODEC = Block.simpleCodec(HangingCreeprootsBlock::new);
public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 0, 4); public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 0, 4);
public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
public static final BooleanProperty STUNTED = BooleanProperty.create("stunted");
private static final int MAX_DISTANCE = 4; private static final int MAX_DISTANCE = 4;
private static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 16.0D, 12.0D); private static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 16.0D, 12.0D);
public HangingCreeprootsBlock(BlockBehaviour.Properties properties) { public HangingCreeprootsBlock(BlockBehaviour.Properties properties) {
super(properties); super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(DISTANCE, 0).setValue(BOTTOM, true)); this.registerDefaultState(this.stateDefinition.any().setValue(DISTANCE, 0).setValue(BOTTOM, true).setValue(STUNTED, false));
} }
@Override @Override
@@ -67,12 +78,12 @@ public class HangingCreeprootsBlock extends BushBlock {
@Override @Override
protected boolean isRandomlyTicking(BlockState state) { protected boolean isRandomlyTicking(BlockState state) {
return state.getValue(BOTTOM) && state.getValue(DISTANCE) < MAX_DISTANCE; return state.getValue(BOTTOM) && !state.getValue(STUNTED) && state.getValue(DISTANCE) < MAX_DISTANCE;
} }
@Override @Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!state.getValue(BOTTOM) || state.getValue(DISTANCE) >= MAX_DISTANCE) { if (state.getValue(STUNTED) || !state.getValue(BOTTOM) || state.getValue(DISTANCE) >= MAX_DISTANCE) {
return; return;
} }
@@ -86,8 +97,23 @@ public class HangingCreeprootsBlock extends BushBlock {
level.setBlock(belowPos, this.defaultBlockState().setValue(DISTANCE, distance + 1).setValue(BOTTOM, true), Block.UPDATE_ALL); level.setBlock(belowPos, this.defaultBlockState().setValue(DISTANCE, distance + 1).setValue(BOTTOM, true), Block.UPDATE_ALL);
} }
@Override
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) {
if (!stack.is(Items.SHEARS) || state.getValue(STUNTED)) {
return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
}
if (!level.isClientSide) {
level.setBlock(pos, state.setValue(STUNTED, true), Block.UPDATE_ALL);
stack.hurtAndBreak(1, player, hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND);
level.playSound(null, pos, SoundEvents.SHEEP_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
}
return ItemInteractionResult.sidedSuccess(level.isClientSide);
}
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(DISTANCE, BOTTOM); builder.add(DISTANCE, BOTTOM, STUNTED);
} }
} }
@@ -6,12 +6,16 @@ import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@@ -36,6 +40,7 @@ public class MoltingVinesBlock extends BushBlock implements BonemealableBlock {
public static final BooleanProperty TOP_CAP = BooleanProperty.create("top_cap"); public static final BooleanProperty TOP_CAP = BooleanProperty.create("top_cap");
public static final BooleanProperty BOTTOM_CAP = BooleanProperty.create("bottom_cap"); public static final BooleanProperty BOTTOM_CAP = BooleanProperty.create("bottom_cap");
public static final BooleanProperty BROODFRUIT = BooleanProperty.create("broodfruit"); public static final BooleanProperty BROODFRUIT = BooleanProperty.create("broodfruit");
public static final BooleanProperty STUNTED = BooleanProperty.create("stunted");
public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 0, 6); public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 0, 6);
private static final int MAX_DISTANCE = 6; private static final int MAX_DISTANCE = 6;
private static final int NATURAL_FRUIT_CHANCE = 40; private static final int NATURAL_FRUIT_CHANCE = 40;
@@ -49,6 +54,7 @@ public class MoltingVinesBlock extends BushBlock implements BonemealableBlock {
.setValue(TOP_CAP, false) .setValue(TOP_CAP, false)
.setValue(BOTTOM_CAP, true) .setValue(BOTTOM_CAP, true)
.setValue(BROODFRUIT, false) .setValue(BROODFRUIT, false)
.setValue(STUNTED, false)
.setValue(DISTANCE, 0)); .setValue(DISTANCE, 0));
} }
@@ -134,11 +140,15 @@ public class MoltingVinesBlock extends BushBlock implements BonemealableBlock {
@Override @Override
protected boolean isRandomlyTicking(BlockState state) { protected boolean isRandomlyTicking(BlockState state) {
return true; return !state.getValue(STUNTED);
} }
@Override @Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (state.getValue(STUNTED)) {
return;
}
boolean isTip = state.getValue(GROWTH_DIRECTION) == Direction.DOWN ? state.getValue(BOTTOM_CAP) : state.getValue(TOP_CAP); boolean isTip = state.getValue(GROWTH_DIRECTION) == Direction.DOWN ? state.getValue(BOTTOM_CAP) : state.getValue(TOP_CAP);
if (isTip && state.getValue(DISTANCE) < MAX_DISTANCE && random.nextInt(6) == 0) { if (isTip && state.getValue(DISTANCE) < MAX_DISTANCE && random.nextInt(6) == 0) {
BlockPos growPos = pos.relative(state.getValue(GROWTH_DIRECTION)); BlockPos growPos = pos.relative(state.getValue(GROWTH_DIRECTION));
@@ -181,6 +191,16 @@ public class MoltingVinesBlock extends BushBlock implements BonemealableBlock {
@Override @Override
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) {
if (stack.is(Items.SHEARS) && !state.getValue(STUNTED)) {
if (!level.isClientSide) {
level.setBlock(pos, state.setValue(STUNTED, true), Block.UPDATE_ALL);
stack.hurtAndBreak(1, player, hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND);
level.playSound(null, pos, SoundEvents.SHEEP_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
}
return ItemInteractionResult.sidedSuccess(level.isClientSide);
}
if (!state.getValue(BROODFRUIT)) { if (!state.getValue(BROODFRUIT)) {
return super.useItemOn(stack, state, level, pos, player, hand, hitResult); return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
} }
@@ -188,6 +208,7 @@ public class MoltingVinesBlock extends BushBlock implements BonemealableBlock {
if (!level.isClientSide) { if (!level.isClientSide) {
BuiltInRegistries.ITEM.getOptional(BROODFRUIT_ITEM_ID).ifPresent(item -> harvestFruit(level, pos, item)); BuiltInRegistries.ITEM.getOptional(BROODFRUIT_ITEM_ID).ifPresent(item -> harvestFruit(level, pos, item));
level.setBlock(pos, state.setValue(BROODFRUIT, false), Block.UPDATE_ALL); level.setBlock(pos, state.setValue(BROODFRUIT, false), Block.UPDATE_ALL);
level.playSound(null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.9F + level.random.nextFloat() * 0.2F);
} }
return ItemInteractionResult.sidedSuccess(level.isClientSide); return ItemInteractionResult.sidedSuccess(level.isClientSide);
@@ -197,8 +218,16 @@ public class MoltingVinesBlock extends BushBlock implements BonemealableBlock {
Block.popResource(level, pos, new ItemStack(item, 1)); Block.popResource(level, pos, new ItemStack(item, 1));
} }
@Override
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
if (!level.isClientSide && state.getValue(BROODFRUIT) && !state.is(newState.getBlock())) {
BuiltInRegistries.ITEM.getOptional(BROODFRUIT_ITEM_ID).ifPresent(item -> harvestFruit(level, pos, item));
}
super.onRemove(state, level, pos, newState, movedByPiston);
}
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(GROWTH_DIRECTION, TOP_CAP, BOTTOM_CAP, BROODFRUIT, DISTANCE); builder.add(GROWTH_DIRECTION, TOP_CAP, BOTTOM_CAP, BROODFRUIT, STUNTED, DISTANCE);
} }
} }
@@ -4,29 +4,41 @@ import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.BonemealableBlock; import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.Fluids;
public class PeachLeavesBlock extends LeavesBlock implements BonemealableBlock { public class PeachLeavesBlock extends LeavesBlock implements BonemealableBlock {
public static final MapCodec<PeachLeavesBlock> CODEC = Block.simpleCodec(PeachLeavesBlock::new); public static final MapCodec<PeachLeavesBlock> CODEC = Block.simpleCodec(PeachLeavesBlock::new);
private static final ResourceLocation HANGING_PEACH_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "hanging_peach"); private static final ResourceLocation HANGING_PEACH_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "hanging_peach");
public static final IntegerProperty PEACH_DISTANCE = IntegerProperty.create("peach_distance", 1, 13);
public static final BooleanProperty PERSISTENT = LeavesBlock.PERSISTENT;
public static final BooleanProperty WATERLOGGED = LeavesBlock.WATERLOGGED;
public static final int PEACH_MAX_DISTANCE = 12;
public static final int PEACH_DECAY_DISTANCE = PEACH_MAX_DISTANCE + 1;
public PeachLeavesBlock(BlockBehaviour.Properties properties) { public PeachLeavesBlock(BlockBehaviour.Properties properties) {
super(properties); super(properties);
this.registerDefaultState(this.defaultBlockState() this.registerDefaultState(this.stateDefinition.any()
.setValue(DISTANCE, DECAY_DISTANCE) .setValue(DISTANCE, DECAY_DISTANCE)
.setValue(PEACH_DISTANCE, PEACH_DECAY_DISTANCE)
.setValue(PERSISTENT, false) .setValue(PERSISTENT, false)
.setValue(WATERLOGGED, false)); .setValue(WATERLOGGED, false));
} }
@@ -39,9 +51,62 @@ public class PeachLeavesBlock extends LeavesBlock implements BonemealableBlock {
@Override @Override
public BlockState getStateForPlacement(BlockPlaceContext context) { public BlockState getStateForPlacement(BlockPlaceContext context) {
FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos());
return this.defaultBlockState() BlockState state = this.defaultBlockState()
.setValue(PERSISTENT, true) .setValue(PERSISTENT, true)
.setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER); .setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER);
return recalculateDistance(state, context.getLevel(), context.getClickedPos());
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(LeavesBlock.DISTANCE, PEACH_DISTANCE, PERSISTENT, WATERLOGGED);
}
@Override
protected boolean isRandomlyTicking(BlockState state) {
return decaying(state);
}
@Override
protected boolean decaying(BlockState state) {
return !state.getValue(PERSISTENT) && state.getValue(PEACH_DISTANCE) > PEACH_MAX_DISTANCE;
}
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (decaying(state)) {
dropResources(state, level, pos);
level.removeBlock(pos, false);
}
}
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
level.setBlock(pos, recalculateDistance(state, level, pos), Block.UPDATE_ALL);
}
@Override
protected BlockState updateShape(
BlockState state,
Direction direction,
BlockState neighborState,
LevelAccessor level,
BlockPos pos,
BlockPos neighborPos
) {
if (state.getValue(WATERLOGGED)) {
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
}
int neighborDistance = Math.min(PEACH_DECAY_DISTANCE, getDistanceAt(neighborState) + 1);
int currentDistance = state.getValue(PEACH_DISTANCE);
if (neighborDistance != 1 || currentDistance != neighborDistance) {
level.scheduleTick(pos, this, 1);
}
return state;
} }
@Override @Override
@@ -85,4 +150,51 @@ public class PeachLeavesBlock extends LeavesBlock implements BonemealableBlock {
.map(Block::defaultBlockState) .map(Block::defaultBlockState)
.orElseThrow(() -> new IllegalStateException("Missing hanging peach block: " + HANGING_PEACH_ID)); .orElseThrow(() -> new IllegalStateException("Missing hanging peach block: " + HANGING_PEACH_ID));
} }
private static BlockState recalculateDistance(BlockState state, LevelReader level, BlockPos pos) {
int bestDistance = PEACH_DECAY_DISTANCE;
BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
for (Direction direction : Direction.values()) {
cursor.setWithOffset(pos, direction);
bestDistance = Math.min(bestDistance, getDistanceAt(level.getBlockState(cursor)) + 1);
if (bestDistance == 1) {
break;
}
}
return setPeachDistance(state, Math.min(PEACH_DECAY_DISTANCE, bestDistance));
}
private static BlockState setPeachDistance(BlockState state, int distance) {
int peachDistance = Math.max(1, Math.min(PEACH_DECAY_DISTANCE, distance));
int vanillaDistance = Math.min(LeavesBlock.DECAY_DISTANCE, peachDistance);
return state
.setValue(PEACH_DISTANCE, peachDistance)
.setValue(LeavesBlock.DISTANCE, vanillaDistance);
}
private static int getDistanceAt(BlockState state) {
if (state.is(BlockTags.LOGS)) {
return 0;
}
if (state.hasProperty(PEACH_DISTANCE)) {
return state.getValue(PEACH_DISTANCE);
}
if (state.hasProperty(LeavesBlock.DISTANCE)) {
return state.getValue(LeavesBlock.DISTANCE);
}
return PEACH_DECAY_DISTANCE;
}
public static BlockState setPeachDistanceForWorldgen(BlockState state, int distance) {
int peachDistance = Math.max(1, Math.min(PEACH_DECAY_DISTANCE, distance));
int vanillaDistance = Math.min(LeavesBlock.DECAY_DISTANCE, peachDistance);
return state
.setValue(PEACH_DISTANCE, peachDistance)
.setValue(LeavesBlock.DISTANCE, vanillaDistance);
}
} }
@@ -0,0 +1,68 @@
package com.craisinlord.antarchy.content.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.PressurePlateBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockSetType;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class PolishedNyxitePressurePlateBlock extends PressurePlateBlock {
public static final BooleanProperty CEILING = BooleanProperty.create("ceiling");
private static final VoxelShape CEILING_SHAPE = Block.box(1.0D, 15.0D, 1.0D, 15.0D, 16.0D, 15.0D);
private static final VoxelShape CEILING_PRESSED_SHAPE = Block.box(1.0D, 15.5D, 1.0D, 15.0D, 16.0D, 15.0D);
private static final AABB CEILING_TOUCH_AABB = new AABB(0.0625D, 0.75D, 0.0625D, 0.9375D, 1.0D, 0.9375D);
public PolishedNyxitePressurePlateBlock(BlockSetType type, BlockBehaviour.Properties properties) {
super(type, properties);
this.registerDefaultState(this.stateDefinition.any().setValue(POWERED, false).setValue(CEILING, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(CEILING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
boolean ceiling = context.getClickedFace() == Direction.DOWN;
return this.defaultBlockState().setValue(CEILING, ceiling);
}
@Override
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
return state.getValue(CEILING)
? Block.canSupportCenter(level, pos.above(), Direction.DOWN)
: super.canSurvive(state, level, pos);
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
if (!state.getValue(CEILING)) {
return super.getShape(state, level, pos, context);
}
return state.getValue(POWERED) ? CEILING_PRESSED_SHAPE : CEILING_SHAPE;
}
@Override
protected int getSignalStrength(Level level, BlockPos pos) {
BlockState state = level.getBlockState(pos);
if (!state.getValue(CEILING)) {
return super.getSignalStrength(level, pos);
}
return getEntityCount(level, CEILING_TOUCH_AABB.move(pos), Entity.class) > 0 ? 15 : 0;
}
}
@@ -101,6 +101,8 @@ public final class CreativeTabContents {
entry("polished_nyxite_stairs", "building_blocks"), entry("polished_nyxite_stairs", "building_blocks"),
entry("polished_nyxite_slab", "building_blocks"), entry("polished_nyxite_slab", "building_blocks"),
entry("polished_nyxite_wall", "building_blocks"), entry("polished_nyxite_wall", "building_blocks"),
entry("polished_nyxite_pressure_plate", "building_blocks"),
entry("polished_nyxite_button", "building_blocks"),
entry("nyxite_bricks", "building_blocks"), entry("nyxite_bricks", "building_blocks"),
entry("nyxite_brick_stairs", "building_blocks"), entry("nyxite_brick_stairs", "building_blocks"),
entry("nyxite_brick_slab", "building_blocks"), entry("nyxite_brick_slab", "building_blocks"),
@@ -112,6 +114,10 @@ public final class CreativeTabContents {
entry("antimetal", "building_blocks"), entry("antimetal", "building_blocks"),
entry("polished_antimetal", "building_blocks"), entry("polished_antimetal", "building_blocks"),
entry("antimetal_scaffolding", "building_blocks"), entry("antimetal_scaffolding", "building_blocks"),
entry("antimetal_rail", "redstone_blocks"),
entry("antimetal_powered_rail", "redstone_blocks"),
entry("antimetal_detector_rail", "redstone_blocks"),
entry("antimetal_activator_rail", "redstone_blocks"),
entry("umbral_moss_block", "building_blocks"), entry("umbral_moss_block", "building_blocks"),
entry("umbral_moss_carpet", "building_blocks"), entry("umbral_moss_carpet", "building_blocks"),
entry("dream_torch", "building_blocks"), entry("dream_torch", "building_blocks"),
@@ -170,10 +176,10 @@ public final class CreativeTabContents {
entry("uranium_trapdoor", "building_blocks"), entry("uranium_trapdoor", "building_blocks"),
entry("uranium_bars", "building_blocks"), entry("uranium_bars", "building_blocks"),
entry("uranium_bulb", "building_blocks"), entry("uranium_bulb", "building_blocks"),
entry("bluestone_block", "building_blocks"), entry("bluestone_block", "redstone_blocks"),
entry("bluestone_repeater", "building_blocks"), entry("bluestone_repeater", "redstone_blocks"),
entry("bluestone_comparator", "building_blocks"), entry("bluestone_comparator", "redstone_blocks"),
entry("bluestone_torch", "building_blocks"), entry("bluestone_torch", "redstone_blocks"),
entry("titanium_block", "building_blocks"), entry("titanium_block", "building_blocks"),
entry("raw_titanium_block", "building_blocks"), entry("raw_titanium_block", "building_blocks"),
entry("cut_titanium", "building_blocks"), entry("cut_titanium", "building_blocks"),
@@ -222,7 +228,7 @@ public final class CreativeTabContents {
entry("deepslate_uranium_ore", "natural_blocks"), entry("deepslate_uranium_ore", "natural_blocks"),
entry("titanium_ore", "natural_blocks"), entry("titanium_ore", "natural_blocks"),
entry("deepslate_titanium_ore", "natural_blocks"), entry("deepslate_titanium_ore", "natural_blocks"),
entry("bluestone_ore", "natural_blocks"), entry("bluestone_ore", "redstone_blocks"),
entry("corn_seeds", "natural_blocks"), entry("corn_seeds", "natural_blocks"),
entry("star_coral", "natural_blocks"), entry("star_coral", "natural_blocks"),
entry("star_coral_fan", "natural_blocks"), entry("star_coral_fan", "natural_blocks"),
@@ -284,7 +290,7 @@ public final class CreativeTabContents {
entry("jumpy_boots", "combat"), entry("jumpy_boots", "combat"),
entry("raw_uranium_scrap", "ingredients"), entry("raw_uranium_scrap", "ingredients"),
entry("raw_titanium_scrap", "ingredients"), entry("raw_titanium_scrap", "ingredients"),
entry("bluestone", "ingredients"), entry("bluestone", "redstone_blocks"),
entry("raw_uranium", "ingredients"), entry("raw_uranium", "ingredients"),
entry("raw_titanium", "ingredients"), entry("raw_titanium", "ingredients"),
entry("uranium_nugget", "ingredients"), entry("uranium_nugget", "ingredients"),
@@ -31,7 +31,7 @@ public final class StinkyBehavior {
if (!(entity.level() instanceof ServerLevel serverLevel)) { if (!(entity.level() instanceof ServerLevel serverLevel)) {
return; return;
} }
if (!entity.isAlive() || !entity.hasEffect(AntarchyObjects.STINKY_EFFECT.get())) { if (!entity.isAlive() || !entity.hasEffect(AntarchyObjects.STINKY_EFFECT.get()) || isSpectatorPlayer(entity)) {
return; return;
} }
if (entity.tickCount % TRAIL_INTERVAL_TICKS != 0) { if (entity.tickCount % TRAIL_INTERVAL_TICKS != 0) {
@@ -84,6 +84,9 @@ public final class StinkyBehavior {
if (!(entity.level() instanceof ServerLevel serverLevel)) { if (!(entity.level() instanceof ServerLevel serverLevel)) {
return; return;
} }
if (isSpectatorPlayer(entity)) {
return;
}
serverLevel.sendParticles( serverLevel.sendParticles(
AntarchyObjects.STINKY_GAS.get(), AntarchyObjects.STINKY_GAS.get(),
entity.getX(), entity.getX(),
@@ -223,4 +226,8 @@ public final class StinkyBehavior {
return !mob.isAlliedTo(source); return !mob.isAlliedTo(source);
} }
private static boolean isSpectatorPlayer(LivingEntity entity) {
return entity instanceof Player player && player.isSpectator();
}
} }
@@ -3,21 +3,21 @@ package com.craisinlord.antarchy.content.entity.lucid;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.projectile.ThrowableProjectile;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import java.util.function.Supplier; import java.util.function.Supplier;
public class LucidBoltEntity extends AbstractArrow { public class LucidBoltEntity extends ThrowableProjectile {
private static final int MAX_LIFETIME_TICKS = 40; private static final int MAX_LIFETIME_TICKS = 40;
private static final int INVERTED_EFFECT_DURATION = 100; private static final int INVERTED_EFFECT_DURATION = 100;
private static final double BASE_DAMAGE = 3.0D; private static final double BASE_DAMAGE = 3.0D;
@@ -30,19 +30,16 @@ public class LucidBoltEntity extends AbstractArrow {
} }
public LucidBoltEntity(EntityType<? extends LucidBoltEntity> entityType, LivingEntity shooter, Level level) { public LucidBoltEntity(EntityType<? extends LucidBoltEntity> entityType, LivingEntity shooter, Level level) {
super(entityType, shooter, level, new ItemStack(Items.BOW), new ItemStack(Items.BOW)); super(entityType, shooter, level);
this.configureBolt(); this.configureBolt();
} }
private void configureBolt() { private void configureBolt() {
this.pickup = Pickup.DISALLOWED;
this.setNoGravity(true); this.setNoGravity(true);
this.setBaseDamage(BASE_DAMAGE);
} }
@Override @Override
protected ItemStack getDefaultPickupItem() { protected void defineSynchedData(SynchedEntityData.Builder builder) {
return ItemStack.EMPTY;
} }
@Override @Override
@@ -50,11 +47,6 @@ public class LucidBoltEntity extends AbstractArrow {
return 0.0D; return 0.0D;
} }
@Override
protected net.minecraft.sounds.SoundEvent getDefaultHitGroundSoundEvent() {
return AntarchySoundEvents.LUCID_BOLT_SOUND.get();
}
@Override @Override
public void tick() { public void tick() {
if (!this.level().isClientSide() && this.tickCount > MAX_LIFETIME_TICKS) { if (!this.level().isClientSide() && this.tickCount > MAX_LIFETIME_TICKS) {
@@ -72,14 +64,12 @@ public class LucidBoltEntity extends AbstractArrow {
return; return;
} }
super.onHitEntity(result);
if (!this.level().isClientSide() && result.getEntity() instanceof LivingEntity target) { if (!this.level().isClientSide() && result.getEntity() instanceof LivingEntity target) {
Entity owner = this.getOwner(); Entity owner = this.getOwner();
if (owner instanceof LivingEntity shooter) { if (owner instanceof LivingEntity shooter) {
target.hurt(this.damageSources().mobAttack(shooter), (float) this.getBaseDamage()); target.hurt(this.damageSources().mobAttack(shooter), (float) BASE_DAMAGE);
} else { } else {
target.hurt(this.damageSources().magic(), (float) this.getBaseDamage()); target.hurt(this.damageSources().magic(), (float) BASE_DAMAGE);
} }
if (invertedEffectSupplier != null) { if (invertedEffectSupplier != null) {
@@ -92,7 +82,9 @@ public class LucidBoltEntity extends AbstractArrow {
@Override @Override
protected void onHitBlock(BlockHitResult result) { protected void onHitBlock(BlockHitResult result) {
super.onHitBlock(result); if (!this.level().isClientSide()) {
this.level().playSound(null, result.getBlockPos(), AntarchySoundEvents.LUCID_BOLT_SOUND.get(), SoundSource.HOSTILE, 0.8F, 1.0F);
}
this.discard(); this.discard();
} }
} }
@@ -1,8 +1,11 @@
package com.craisinlord.antarchy.content.fluid; package com.craisinlord.antarchy.content.fluid;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
public final class AntarchyFluidChecks { public final class AntarchyFluidChecks {
@@ -14,6 +17,7 @@ public final class AntarchyFluidChecks {
private static final ResourceLocation FLOWING_LUMEN_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "flowing_lumen"); private static final ResourceLocation FLOWING_LUMEN_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "flowing_lumen");
private static final ResourceLocation BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile"); private static final ResourceLocation BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile");
private static final ResourceLocation FLOWING_BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "flowing_bile"); private static final ResourceLocation FLOWING_BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "flowing_bile");
private static final ResourceLocation BILE_VEIN_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile_vein");
private AntarchyFluidChecks() { private AntarchyFluidChecks() {
} }
@@ -41,4 +45,30 @@ public final class AntarchyFluidChecks {
public static boolean usesWaterLikePhysics(FluidState fluidState) { public static boolean usesWaterLikePhysics(FluidState fluidState) {
return isIchor(fluidState) || isLumen(fluidState) || isBile(fluidState); return isIchor(fluidState) || isLumen(fluidState) || isBile(fluidState);
} }
public static boolean isBileVein(BlockState state) {
ResourceLocation blockId = BuiltInRegistries.BLOCK.getKey(state.getBlock());
return BILE_VEIN_ID.equals(blockId);
}
/**
* Bile always wins: worldgen foliage must not anchor on or near bile fluid or its solid
* bile_vein shell, since cyst/vein features can carve into a neighboring chunk after this
* chunk's vegetation has already been placed.
*/
public static boolean hasBileNearby(LevelAccessor level, BlockPos center, int radius) {
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (int dx = -radius; dx <= radius; dx++) {
for (int dy = -radius; dy <= radius; dy++) {
for (int dz = -radius; dz <= radius; dz++) {
mutable.set(center.getX() + dx, center.getY() + dy, center.getZ() + dz);
BlockState state = level.getBlockState(mutable);
if (isBile(state.getFluidState()) || isBileVein(state)) {
return true;
}
}
}
}
return false;
}
} }
@@ -326,7 +326,7 @@ public final class CavarynHordeManager {
private static void tickDormantPressure(ServerLevel level, HordeData data, ServerPlayer player, PlayerAttention attention, long areaKey, long gameTime) { private static void tickDormantPressure(ServerLevel level, HordeData data, ServerPlayer player, PlayerAttention attention, long areaKey, long gameTime) {
long nextSpawnTime = data.areaSpawnCooldowns.getOrDefault(areaKey, 0L); long nextSpawnTime = data.areaSpawnCooldowns.getOrDefault(areaKey, 0L);
if (gameTime < nextSpawnTime || level.getDifficulty() == Difficulty.PEACEFUL) { if (gameTime < nextSpawnTime || level.getDifficulty() == Difficulty.PEACEFUL || !mobSpawningEnabled(level)) {
return; return;
} }
@@ -435,7 +435,7 @@ public final class CavarynHordeManager {
} }
private static void spawnAwakeningSkirmish(ServerLevel level, Encounter encounter, List<ServerPlayer> targets) { private static void spawnAwakeningSkirmish(ServerLevel level, Encounter encounter, List<ServerPlayer> targets) {
if (level.getDifficulty() == Difficulty.PEACEFUL) { if (level.getDifficulty() == Difficulty.PEACEFUL || !mobSpawningEnabled(level)) {
return; return;
} }
int players = Math.max(1, targets.size()); int players = Math.max(1, targets.size());
@@ -457,7 +457,7 @@ public final class CavarynHordeManager {
} }
private static void spawnPulse(ServerLevel level, Encounter encounter, List<ServerPlayer> targets) { private static void spawnPulse(ServerLevel level, Encounter encounter, List<ServerPlayer> targets) {
if (level.getDifficulty() == Difficulty.PEACEFUL) { if (level.getDifficulty() == Difficulty.PEACEFUL || !mobSpawningEnabled(level)) {
return; return;
} }
@@ -485,6 +485,9 @@ public final class CavarynHordeManager {
} }
private static boolean spawnDirectMob(ServerLevel level, @Nullable Encounter encounter, CavarynHordeDefinitions.SpawnChoice choice, ServerPlayer target) { private static boolean spawnDirectMob(ServerLevel level, @Nullable Encounter encounter, CavarynHordeDefinitions.SpawnChoice choice, ServerPlayer target) {
if (!mobSpawningEnabled(level)) {
return false;
}
EntityType<?> type = choice.type(); EntityType<?> type = choice.type();
BlockPos spawnPos = findSpawnPos(level, target, type, level.random); BlockPos spawnPos = findSpawnPos(level, target, type, level.random);
if (spawnPos == null) { if (spawnPos == null) {
@@ -635,6 +638,10 @@ public final class CavarynHordeManager {
return level.getGameRules().getBoolean(AntarchyGameRules.RULE_DO_CAVARYN_HORDES); return level.getGameRules().getBoolean(AntarchyGameRules.RULE_DO_CAVARYN_HORDES);
} }
private static boolean mobSpawningEnabled(ServerLevel level) {
return level.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DOMOBSPAWNING);
}
private static void clearDisabledState(ServerLevel level, HordeData data) { private static void clearDisabledState(ServerLevel level, HordeData data) {
boolean dirty = false; boolean dirty = false;
if (!data.encounters.isEmpty()) { if (!data.encounters.isEmpty()) {
@@ -26,7 +26,7 @@ public class BluestoneDustItem extends Item {
@Override @Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) { public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.bluestone_placement").withStyle(ChatFormatting.BLUE)); tooltipComponents.add(Component.translatable("tooltip.antarchy.bluestone_placement").withStyle(ChatFormatting.DARK_AQUA));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
} }
@@ -0,0 +1,22 @@
package com.craisinlord.antarchy.content.item;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.block.Block;
public class CeilingCompatiblePlacementTooltipBlockItem extends BlockItem {
public CeilingCompatiblePlacementTooltipBlockItem(Block block, Properties properties) {
super(block, properties);
}
@Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.ceiling_compatible_placement").withStyle(ChatFormatting.DARK_AQUA));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
}
}
@@ -16,7 +16,7 @@ public class CeilingPlacementTooltipBlockItem extends BlockItem {
@Override @Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) { public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.bluestone_placement").withStyle(ChatFormatting.BLUE)); tooltipComponents.add(Component.translatable("tooltip.antarchy.bluestone_placement").withStyle(ChatFormatting.DARK_AQUA));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
} }
} }
@@ -14,7 +14,7 @@ public class CeilingPlacementTooltipItem extends Item {
@Override @Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) { public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.bluestone_placement").withStyle(ChatFormatting.BLUE)); tooltipComponents.add(Component.translatable("tooltip.antarchy.bluestone_placement").withStyle(ChatFormatting.DARK_AQUA));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
} }
} }
@@ -0,0 +1,66 @@
package com.craisinlord.antarchy.content.minecart;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
public final class AntimetalDismountHelper {
private static final Vec3[] SEARCH_OFFSETS = new Vec3[]{
new Vec3(-1, -1, 0),
new Vec3(1, -1, 0),
new Vec3(0, -1, -1),
new Vec3(0, -1, 1),
new Vec3(-1, -1, -1),
new Vec3(-1, -1, 1),
new Vec3(1, -1, -1),
new Vec3(1, -1, 1),
new Vec3(0, -1.6, 0)
};
private AntimetalDismountHelper() {
}
public static Vec3 findDismountPosition(AbstractMinecart cart, LivingEntity passenger) {
Level level = cart.level();
Vec3 cartPos = cart.position();
double width = Math.max(passenger.getBbWidth(), 0.6D);
double height = passenger.getBbHeight();
for (Vec3 offset : SEARCH_OFFSETS) {
Vec3 candidate = cartPos.add(offset);
if (isClear(level, candidate, width, height)) {
return candidate;
}
}
return cartPos.add(0, -1.0D, 0);
}
private static boolean isClear(Level level, Vec3 pos, double width, double height) {
AABB box = new AABB(
pos.x - width / 2.0D, pos.y, pos.z - width / 2.0D,
pos.x + width / 2.0D, pos.y + height, pos.z + width / 2.0D
);
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
int minX = net.minecraft.util.Mth.floor(box.minX);
int maxX = net.minecraft.util.Mth.floor(box.maxX);
int minY = net.minecraft.util.Mth.floor(box.minY);
int maxY = net.minecraft.util.Mth.floor(box.maxY);
int minZ = net.minecraft.util.Mth.floor(box.minZ);
int maxZ = net.minecraft.util.Mth.floor(box.maxZ);
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
mutable.set(x, y, z);
if (!level.getBlockState(mutable).getCollisionShape(level, mutable).isEmpty()) {
return false;
}
}
}
}
return true;
}
}
@@ -0,0 +1,15 @@
package com.craisinlord.antarchy.content.minecart;
import net.minecraft.core.BlockPos;
import org.jetbrains.annotations.Nullable;
public interface AntimetalMinecartAccess {
boolean antarchy$isOnAntimetalRail();
void antarchy$setOnAntimetalRail(boolean value);
@Nullable
BlockPos antarchy$getAntimetalRailPos();
void antarchy$setAntimetalRailPos(@Nullable BlockPos pos);
}
@@ -0,0 +1,339 @@
package com.craisinlord.antarchy.content.minecart;
import com.craisinlord.antarchy.content.block.AbstractAntimetalRailBlock;
import com.craisinlord.antarchy.content.block.AntimetalActivatorRailBlock;
import com.craisinlord.antarchy.content.block.AntimetalPoweredRailBlock;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
/**
* A direct mirror of {@code AbstractMinecart.moveAlongTrack}/{@code getPos}/{@code getPosOffs},
* adapted for ceiling-mounted track. The world-Y meaning of "ascending"/"descending" does not
* need to be sign-flipped anywhere here — lower world Y is lower world Y whether a rail rests on
* a floor or hangs from a ceiling. What actually differs from vanilla is: the rail sits near the
* top of its cell instead of near the bottom (see {@link AntimetalRailHelper#attachY}), support
* is required above instead of below, and the "which cell owns this position" disambiguation
* checks the cell above instead of the cell below. Everything else — the exit-projection math,
* the slope acceleration constant, the player-push nudge, using real collision-checked
* {@code Entity.move} rather than a hand-rolled collision test — is a straight port.
*/
public final class AntimetalMinecartPhysics {
private static final double SLOPE_ACCEL = 0.0078125D;
private static final double MAX_RAIL_SPEED = 0.4D;
private static final double RAIL_ACCELERATION = 0.06D;
private static final double HITBOX_DROP = 0.4625D;
private AntimetalMinecartPhysics() {
}
@Nullable
public static BlockPos findCell(Level level, double x, double y, double z) {
int i = Mth.floor(x);
int j = Mth.floor(y);
int k = Mth.floor(z);
BlockPos direct = new BlockPos(i, j, k);
if (isAntimetalRailAt(level, direct)) {
return direct;
}
BlockPos above = direct.above();
return isAntimetalRailAt(level, above) ? above : null;
}
public static boolean isAntimetalRailAt(Level level, BlockPos pos) {
return AbstractAntimetalRailBlock.isAntimetalRail(level.getBlockState(pos));
}
private static boolean isAntimetalRailAt(Level level, int x, int y, int z) {
return isAntimetalRailAt(level, new BlockPos(x, y, z));
}
@Nullable
private static Vec3 ascendingPosition(RailShape shape, BlockPos cell, double x, double z) {
double baseY = AntimetalRailHelper.attachY(cell.getY(), 0);
double centerX = cell.getX() + 0.5D;
double centerZ = cell.getZ() + 0.5D;
return switch (shape) {
case ASCENDING_EAST -> {
double t = Mth.clamp(cell.getX() + 1.0D - x, 0.0D, 1.0D);
yield new Vec3(cell.getX() + 1.0D - t, baseY - t, centerZ);
}
case ASCENDING_WEST -> {
double t = Mth.clamp(x - cell.getX(), 0.0D, 1.0D);
yield new Vec3(cell.getX() + t, baseY - t, centerZ);
}
case ASCENDING_NORTH -> {
double t = Mth.clamp(z - cell.getZ(), 0.0D, 1.0D);
yield new Vec3(centerX, baseY - t, cell.getZ() + t);
}
case ASCENDING_SOUTH -> {
double t = Mth.clamp(cell.getZ() + 1.0D - z, 0.0D, 1.0D);
yield new Vec3(centerX, baseY - t, cell.getZ() + 1.0D - t);
}
default -> null;
};
}
public static void moveAlongTrack(AbstractMinecart cart, BlockPos railPos, BlockState railState) {
cart.resetFallDistance();
double x = cart.getX();
double y = cart.getY();
double z = cart.getZ();
Vec3 before = getPos(cart, x, y, z);
double targetY = AntimetalRailHelper.attachY(railPos.getY(), 0);
boolean poweredOn = false;
boolean unpoweredBraking = false;
if (railState.getBlock() instanceof AntimetalPoweredRailBlock) {
poweredOn = railState.getValue(AntimetalPoweredRailBlock.POWERED);
unpoweredBraking = !poweredOn;
}
RailShape shape = railState.getValue(((AbstractAntimetalRailBlock) railState.getBlock()).getShapeProperty());
Vec3 motion = cart.getDeltaMovement();
switch (shape) {
case ASCENDING_EAST -> cart.setDeltaMovement(motion.add(-SLOPE_ACCEL, 0.0D, 0.0D));
case ASCENDING_WEST -> cart.setDeltaMovement(motion.add(SLOPE_ACCEL, 0.0D, 0.0D));
case ASCENDING_NORTH -> cart.setDeltaMovement(motion.add(0.0D, 0.0D, SLOPE_ACCEL));
case ASCENDING_SOUTH -> cart.setDeltaMovement(motion.add(0.0D, 0.0D, -SLOPE_ACCEL));
default -> {
}
}
motion = cart.getDeltaMovement();
Pair<Vec3i, Vec3i> exits = AntimetalRailHelper.getExits(shape);
Vec3i exitA = exits.getFirst();
Vec3i exitB = exits.getSecond();
double dx = exitB.getX() - exitA.getX();
double dz = exitB.getZ() - exitA.getZ();
double dirLength = Math.sqrt(dx * dx + dz * dz);
double alignment = motion.x * dx + motion.z * dz;
if (alignment < 0.0D) {
dx = -dx;
dz = -dz;
}
double speed = Math.min(2.0D, motion.horizontalDistance());
motion = new Vec3(speed * dx / dirLength, motion.y, speed * dz / dirLength);
cart.setDeltaMovement(motion);
Entity firstPassenger = cart.getFirstPassenger();
if (firstPassenger instanceof Player) {
Vec3 riderMotion = firstPassenger.getDeltaMovement();
double riderSpeedSq = riderMotion.horizontalDistanceSqr();
double cartSpeedSq = cart.getDeltaMovement().horizontalDistanceSqr();
if (riderSpeedSq > 1.0E-4D && cartSpeedSq < 0.01D) {
cart.setDeltaMovement(cart.getDeltaMovement().add(riderMotion.x * 0.1D, 0.0D, riderMotion.z * 0.1D));
unpoweredBraking = false;
}
}
if (unpoweredBraking) {
double brakingSpeed = cart.getDeltaMovement().horizontalDistance();
if (brakingSpeed < 0.03D) {
cart.setDeltaMovement(Vec3.ZERO);
} else {
cart.setDeltaMovement(cart.getDeltaMovement().multiply(0.5D, 0.0D, 0.5D));
}
}
Vec3 ascendingPos = shape.isAscending() ? ascendingPosition(shape, railPos, x, z) : null;
if (ascendingPos != null) {
x = ascendingPos.x;
targetY = ascendingPos.y;
z = ascendingPos.z;
} else {
double startX = railPos.getX() + 0.5D + exitA.getX() * 0.5D;
double startZ = railPos.getZ() + 0.5D + exitA.getZ() * 0.5D;
double endX = railPos.getX() + 0.5D + exitB.getX() * 0.5D;
double endZ = railPos.getZ() + 0.5D + exitB.getZ() * 0.5D;
dx = endX - startX;
dz = endZ - startZ;
double s;
if (dx == 0.0D) {
s = z - railPos.getZ();
} else if (dz == 0.0D) {
s = x - railPos.getX();
} else {
double px = x - startX;
double pz = z - startZ;
s = (px * dx + pz * dz) * 2.0D;
}
x = startX + dx * s;
z = startZ + dz * s;
}
cart.setPos(x, targetY, z);
cart.setBoundingBox(cart.getBoundingBox().move(0.0D, -HITBOX_DROP, 0.0D));
double passengerFactor = cart.isVehicle() ? 0.75D : 1.0D;
motion = cart.getDeltaMovement();
Vec3 clampedMotion = new Vec3(
Mth.clamp(passengerFactor * motion.x, -MAX_RAIL_SPEED, MAX_RAIL_SPEED),
0.0D,
Mth.clamp(passengerFactor * motion.z, -MAX_RAIL_SPEED, MAX_RAIL_SPEED)
);
if (shape.isAscending()) {
cart.setPos(cart.getX() + clampedMotion.x, cart.getY(), cart.getZ() + clampedMotion.z);
} else {
cart.move(MoverType.SELF, clampedMotion);
}
if (exitA.getY() != 0 && Mth.floor(cart.getX()) - railPos.getX() == exitA.getX() && Mth.floor(cart.getZ()) - railPos.getZ() == exitA.getZ()) {
cart.setPos(cart.getX(), cart.getY() + exitA.getY(), cart.getZ());
} else if (exitB.getY() != 0 && Mth.floor(cart.getX()) - railPos.getX() == exitB.getX() && Mth.floor(cart.getZ()) - railPos.getZ() == exitB.getZ()) {
cart.setPos(cart.getX(), cart.getY() + exitB.getY(), cart.getZ());
}
applyNaturalSlowdown(cart);
Vec3 after = getPos(cart, cart.getX(), cart.getY(), cart.getZ());
if (after != null && before != null) {
double slopeDelta = (before.y - after.y) * 0.05D;
Vec3 currentMotion = cart.getDeltaMovement();
double horizontalSpeed = currentMotion.horizontalDistance();
if (horizontalSpeed > 0.0D) {
cart.setDeltaMovement(currentMotion.multiply((horizontalSpeed + slopeDelta) / horizontalSpeed, 1.0D, (horizontalSpeed + slopeDelta) / horizontalSpeed));
}
cart.setPos(cart.getX(), after.y, cart.getZ());
}
int cellX = Mth.floor(cart.getX());
int cellZ = Mth.floor(cart.getZ());
if (cellX != railPos.getX() || cellZ != railPos.getZ()) {
Vec3 currentMotion = cart.getDeltaMovement();
double horizontalSpeed = currentMotion.horizontalDistance();
cart.setDeltaMovement(horizontalSpeed * (cellX - railPos.getX()), currentMotion.y, horizontalSpeed * (cellZ - railPos.getZ()));
}
cart.setBoundingBox(cart.getBoundingBox().move(0.0D, -HITBOX_DROP, 0.0D));
if (poweredOn) {
Vec3 currentMotion = cart.getDeltaMovement();
double horizontalSpeed = currentMotion.horizontalDistance();
if (horizontalSpeed > 0.01D) {
cart.setDeltaMovement(currentMotion.add(currentMotion.x / horizontalSpeed * RAIL_ACCELERATION, 0.0D, currentMotion.z / horizontalSpeed * RAIL_ACCELERATION));
} else if (shape == RailShape.EAST_WEST) {
Vec3 currentMotion2 = cart.getDeltaMovement();
double nudgeX = currentMotion2.x;
if (isRedstoneConductor(cart.level(), railPos.west())) {
nudgeX = 0.02D;
} else if (isRedstoneConductor(cart.level(), railPos.east())) {
nudgeX = -0.02D;
}
cart.setDeltaMovement(nudgeX, currentMotion2.y, currentMotion2.z);
} else if (shape == RailShape.NORTH_SOUTH) {
Vec3 currentMotion2 = cart.getDeltaMovement();
double nudgeZ = currentMotion2.z;
if (isRedstoneConductor(cart.level(), railPos.north())) {
nudgeZ = 0.02D;
} else if (isRedstoneConductor(cart.level(), railPos.south())) {
nudgeZ = -0.02D;
}
cart.setDeltaMovement(currentMotion2.x, currentMotion2.y, nudgeZ);
}
}
if (railState.getBlock() instanceof AntimetalActivatorRailBlock && railState.getValue(AntimetalActivatorRailBlock.POWERED)) {
cart.activateMinecart(railPos.getX(), railPos.getY(), railPos.getZ(), true);
}
}
private static boolean isRedstoneConductor(Level level, BlockPos pos) {
return level.getBlockState(pos).isRedstoneConductor(level, pos);
}
private static void applyNaturalSlowdown(AbstractMinecart cart) {
double drag = cart.isVehicle() ? 0.997D : 0.96D;
Vec3 motion = cart.getDeltaMovement();
cart.setDeltaMovement(motion.multiply(drag, 0.0D, drag));
}
@Nullable
public static Vec3 getPosOffs(AbstractMinecart cart, double x, double y, double z, double offset) {
BlockPos cell = findCell(cart.level(), x, y, z);
if (cell == null) {
return null;
}
BlockState state = cart.level().getBlockState(cell);
RailShape shape = state.getValue(((AbstractAntimetalRailBlock) state.getBlock()).getShapeProperty());
double targetY = AntimetalRailHelper.attachY(cell.getY(), 0);
Pair<Vec3i, Vec3i> exits = AntimetalRailHelper.getExits(shape);
Vec3i exitA = exits.getFirst();
Vec3i exitB = exits.getSecond();
double dx = exitB.getX() - exitA.getX();
double dz = exitB.getZ() - exitA.getZ();
double length = Math.sqrt(dx * dx + dz * dz);
dx /= length;
dz /= length;
x += dx * offset;
z += dz * offset;
if (exitA.getY() != 0 && Mth.floor(x) - cell.getX() == exitA.getX() && Mth.floor(z) - cell.getZ() == exitA.getZ()) {
targetY += exitA.getY();
} else if (exitB.getY() != 0 && Mth.floor(x) - cell.getX() == exitB.getX() && Mth.floor(z) - cell.getZ() == exitB.getZ()) {
targetY += exitB.getY();
}
Vec3 result = getPos(cart, x, targetY, z);
if (result != null && (shape == RailShape.ASCENDING_NORTH || shape == RailShape.ASCENDING_SOUTH)) {
double baseY = AntimetalRailHelper.attachY(cell.getY(), 0);
double mirroredY = 2.0D * (baseY - 0.5D) - result.y;
result = new Vec3(result.x, mirroredY, result.z);
}
return result;
}
@Nullable
public static Vec3 getPos(AbstractMinecart cart, double x, double y, double z) {
BlockPos cell = findCell(cart.level(), x, y, z);
if (cell == null) {
return null;
}
BlockState state = cart.level().getBlockState(cell);
RailShape shape = state.getValue(((AbstractAntimetalRailBlock) state.getBlock()).getShapeProperty());
Vec3 ascendingPos = shape.isAscending() ? ascendingPosition(shape, cell, x, z) : null;
if (ascendingPos != null) {
return ascendingPos;
}
Pair<Vec3i, Vec3i> exits = AntimetalRailHelper.getExits(shape);
Vec3i exitA = exits.getFirst();
Vec3i exitB = exits.getSecond();
double startX = cell.getX() + 0.5D + exitA.getX() * 0.5D;
double startY = AntimetalRailHelper.attachY(cell.getY(), 0) + exitA.getY() * 0.5D;
double startZ = cell.getZ() + 0.5D + exitA.getZ() * 0.5D;
double endX = cell.getX() + 0.5D + exitB.getX() * 0.5D;
double endY = AntimetalRailHelper.attachY(cell.getY(), 0) + exitB.getY() * 0.5D;
double endZ = cell.getZ() + 0.5D + exitB.getZ() * 0.5D;
double dx = endX - startX;
double dy = (endY - startY) * 2.0D;
double dz = endZ - startZ;
double s;
if (dx == 0.0D) {
s = z - cell.getZ();
} else if (dz == 0.0D) {
s = x - cell.getX();
} else {
double px = x - startX;
double pz = z - startZ;
s = (px * dx + pz * dz) * 2.0D;
}
x = startX + dx * s;
y = startY + dy * s;
z = startZ + dz * s;
return new Vec3(x, y, z);
}
}
@@ -0,0 +1,122 @@
package com.craisinlord.antarchy.content.minecart;
import com.craisinlord.antarchy.content.block.AbstractAntimetalRailBlock;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.RailShape;
import java.util.EnumMap;
import java.util.Map;
public final class AntimetalRailHelper {
public static final double RAIL_TOP_OFFSET = 0.0625D;
public static final double CART_MODEL_HEIGHT = 0.7D;
public static final double CART_HANG_OFFSET = CART_MODEL_HEIGHT - 0.1875D;
public static final double CART_MODEL_PIVOT_Y = CART_MODEL_HEIGHT / 2.0D;
private static final Map<RailShape, Pair<Vec3i, Vec3i>> ANTIMETAL_EXITS = new EnumMap<>(RailShape.class);
static {
ANTIMETAL_EXITS.put(RailShape.NORTH_SOUTH, Pair.of(new Vec3i(0, 0, -1), new Vec3i(0, 0, 1)));
ANTIMETAL_EXITS.put(RailShape.EAST_WEST, Pair.of(new Vec3i(-1, 0, 0), new Vec3i(1, 0, 0)));
ANTIMETAL_EXITS.put(RailShape.ASCENDING_EAST, Pair.of(new Vec3i(-1, -1, 0), new Vec3i(1, 0, 0)));
ANTIMETAL_EXITS.put(RailShape.ASCENDING_WEST, Pair.of(new Vec3i(-1, 0, 0), new Vec3i(1, -1, 0)));
ANTIMETAL_EXITS.put(RailShape.ASCENDING_NORTH, Pair.of(new Vec3i(0, 0, -1), new Vec3i(0, -1, 1)));
ANTIMETAL_EXITS.put(RailShape.ASCENDING_SOUTH, Pair.of(new Vec3i(0, -1, -1), new Vec3i(0, 0, 1)));
ANTIMETAL_EXITS.put(RailShape.SOUTH_EAST, Pair.of(new Vec3i(0, 0, 1), new Vec3i(1, 0, 0)));
ANTIMETAL_EXITS.put(RailShape.SOUTH_WEST, Pair.of(new Vec3i(0, 0, 1), new Vec3i(-1, 0, 0)));
ANTIMETAL_EXITS.put(RailShape.NORTH_WEST, Pair.of(new Vec3i(0, 0, -1), new Vec3i(-1, 0, 0)));
ANTIMETAL_EXITS.put(RailShape.NORTH_EAST, Pair.of(new Vec3i(0, 0, -1), new Vec3i(1, 0, 0)));
}
private AntimetalRailHelper() {
}
public static Pair<Vec3i, Vec3i> getExits(RailShape shape) {
return ANTIMETAL_EXITS.get(shape);
}
public static double attachY(int railY, int exitDy) {
return railY + exitDy + 1.0D - RAIL_TOP_OFFSET - CART_HANG_OFFSET;
}
private static boolean isRail(LevelReader level, BlockPos pos) {
return AbstractAntimetalRailBlock.isAntimetalRail(level.getBlockState(pos));
}
private static RailShape computeShape(AbstractAntimetalRailBlock block, LevelReader level, BlockPos pos, Direction.Axis fallbackAxis) {
boolean northDown = isRail(level, pos.north().below());
boolean southDown = isRail(level, pos.south().below());
boolean eastDown = isRail(level, pos.east().below());
boolean westDown = isRail(level, pos.west().below());
boolean north = isRail(level, pos.north()) || isRail(level, pos.north().above()) || northDown;
boolean south = isRail(level, pos.south()) || isRail(level, pos.south().above()) || southDown;
boolean east = isRail(level, pos.east()) || isRail(level, pos.east().above()) || eastDown;
boolean west = isRail(level, pos.west()) || isRail(level, pos.west().above()) || westDown;
if (block.isStraight()) {
if (northDown) return RailShape.ASCENDING_SOUTH;
if (southDown) return RailShape.ASCENDING_NORTH;
if (eastDown) return RailShape.ASCENDING_WEST;
if (westDown) return RailShape.ASCENDING_EAST;
if ((east || west) && !(north || south)) return RailShape.EAST_WEST;
if ((north || south) && !(east || west)) return RailShape.NORTH_SOUTH;
return fallbackAxis == Direction.Axis.X ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH;
}
if (northDown) return RailShape.ASCENDING_SOUTH;
if (southDown) return RailShape.ASCENDING_NORTH;
if (eastDown) return RailShape.ASCENDING_WEST;
if (westDown) return RailShape.ASCENDING_EAST;
if (south && east && !north && !west) return RailShape.SOUTH_EAST;
if (south && west && !north && !east) return RailShape.SOUTH_WEST;
if (north && west && !south && !east) return RailShape.NORTH_WEST;
if (north && east && !south && !west) return RailShape.NORTH_EAST;
if ((east || west) && !(north || south)) return RailShape.EAST_WEST;
if ((north || south) && !(east || west)) return RailShape.NORTH_SOUTH;
return fallbackAxis == Direction.Axis.X ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH;
}
public static BlockState getStateForPlacement(AbstractAntimetalRailBlock block, BlockPlaceContext context) {
Direction.Axis axis = context.getHorizontalDirection().getAxis();
RailShape shape = computeShape(block, context.getLevel(), context.getClickedPos(), axis);
return block.defaultBlockState().setValue(block.getShapeProperty(), shape);
}
public static void updateConnections(AbstractAntimetalRailBlock block, BlockState state, LevelAccessor level, BlockPos pos) {
if (!(level instanceof Level realLevel) || realLevel.isClientSide()) {
return;
}
RailShape shape = computeShape(block, realLevel, pos, Direction.Axis.Z);
if (state.getValue(block.getShapeProperty()) != shape) {
realLevel.setBlock(pos, state.setValue(block.getShapeProperty(), shape), 3);
}
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos horizontalPos = pos.relative(direction);
recomputeIfRail(realLevel, horizontalPos);
recomputeIfRail(realLevel, horizontalPos.above());
recomputeIfRail(realLevel, horizontalPos.below());
}
}
private static void recomputeIfRail(Level level, BlockPos pos) {
BlockState state = level.getBlockState(pos);
if (state.getBlock() instanceof AbstractAntimetalRailBlock block) {
RailShape shape = computeShape(block, level, pos, Direction.Axis.Z);
if (state.getValue(block.getShapeProperty()) != shape) {
level.setBlock(pos, state.setValue(block.getShapeProperty(), shape), 3);
}
}
}
}
@@ -60,7 +60,7 @@ public final class CavarynBileCystFeature extends Feature<NoneFeatureConfigurati
y = Mth.clamp(y, level.getMinBuildHeight() + 6, level.getMaxBuildHeight() - 6); y = Mth.clamp(y, level.getMinBuildHeight() + 6, level.getMaxBuildHeight() - 6);
mutable.set(x, y, z); mutable.set(x, y, z);
if (!isSolid(level.getBlockState(mutable))) { if (!isSolid(level, mutable)) {
continue; continue;
} }
@@ -77,7 +77,7 @@ public final class CavarynBileCystFeature extends Feature<NoneFeatureConfigurati
int depth = 1 + random.nextInt(2); int depth = 1 + random.nextInt(2);
BlockPos candidate = mutable.immutable().relative(openDir.getOpposite(), depth); BlockPos candidate = mutable.immutable().relative(openDir.getOpposite(), depth);
if (isSolid(level.getBlockState(candidate))) { if (isSolid(level, candidate)) {
return candidate; return candidate;
} }
} }
@@ -124,8 +124,7 @@ public final class CavarynBileCystFeature extends Feature<NoneFeatureConfigurati
} }
BlockPos pos = center.offset(dx, dy, dz); BlockPos pos = center.offset(dx, dy, dz);
BlockState existing = level.getBlockState(pos); if (!isSolid(level, pos)) {
if (!isSolid(existing)) {
continue; continue;
} }
@@ -151,7 +150,9 @@ public final class CavarynBileCystFeature extends Feature<NoneFeatureConfigurati
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
BlockPos adj = cystPos.relative(dir); BlockPos adj = cystPos.relative(dir);
BlockState adjState = level.getBlockState(adj); BlockState adjState = level.getBlockState(adj);
if ((adjState.isAir() || adjState.canBeReplaced()) && random.nextFloat() < OOZE_CHANCE) { if ((adjState.isAir() || adjState.canBeReplaced())
&& !CavarynFoliageGuard.isFoliageNearby(level, adj)
&& random.nextFloat() < OOZE_CHANCE) {
BlockState bileState = bileBlock.defaultBlockState(); BlockState bileState = bileBlock.defaultBlockState();
level.setBlock(adj, bileState, 2); level.setBlock(adj, bileState, 2);
scheduleFluidTick(level, adj, bileState); scheduleFluidTick(level, adj, bileState);
@@ -162,8 +163,10 @@ public final class CavarynBileCystFeature extends Feature<NoneFeatureConfigurati
return true; return true;
} }
private static boolean isSolid(BlockState state) { private static boolean isSolid(WorldGenLevel level, BlockPos pos) {
return state.blocksMotion() && !state.is(Blocks.BEDROCK) && state.getFluidState().isEmpty(); BlockState state = level.getBlockState(pos);
return state.blocksMotion() && !state.is(Blocks.BEDROCK) && state.getFluidState().isEmpty()
&& !CavarynFoliageGuard.isFoliageNearby(level, pos);
} }
private static void scheduleFluidTick(WorldGenLevel level, BlockPos pos, BlockState state) { private static void scheduleFluidTick(WorldGenLevel level, BlockPos pos, BlockState state) {
@@ -68,7 +68,7 @@ public final class CavarynBileVeinFeature extends Feature<NoneFeatureConfigurati
y = Mth.clamp(y, level.getMinBuildHeight() + 2, level.getMaxBuildHeight() - 3); y = Mth.clamp(y, level.getMinBuildHeight() + 2, level.getMaxBuildHeight() - 3);
mutable.set(x, y, z); mutable.set(x, y, z);
if (!isVeinCandidate(level.getBlockState(mutable))) { if (!isVeinCandidate(level, mutable)) {
continue; continue;
} }
@@ -124,15 +124,13 @@ public final class CavarynBileVeinFeature extends Feature<NoneFeatureConfigurati
continue; continue;
} }
BlockState state = level.getBlockState(current); if (!isVeinCandidate(level, current)) {
if (!isVeinCandidate(state)) {
BlockPos redirect = findSolidNeighbor(current, dir, visited, level, random); BlockPos redirect = findSolidNeighbor(current, dir, visited, level, random);
if (redirect == null) { if (redirect == null) {
break; break;
} }
current = redirect; current = redirect;
state = level.getBlockState(current); if (!isVeinCandidate(level, current)) {
if (!isVeinCandidate(state)) {
break; break;
} }
} }
@@ -175,7 +173,7 @@ public final class CavarynBileVeinFeature extends Feature<NoneFeatureConfigurati
} }
for (Direction d : perps) { for (Direction d : perps) {
BlockPos candidate = from.relative(d); BlockPos candidate = from.relative(d);
if (!visited.contains(candidate) && isVeinCandidate(level.getBlockState(candidate))) { if (!visited.contains(candidate) && isVeinCandidate(level, candidate)) {
return candidate; return candidate;
} }
} }
@@ -195,8 +193,7 @@ public final class CavarynBileVeinFeature extends Feature<NoneFeatureConfigurati
if (visited.contains(candidate)) { if (visited.contains(candidate)) {
continue; continue;
} }
BlockState candidateState = level.getBlockState(candidate); if (!isVeinCandidate(level, candidate)) {
if (!isVeinCandidate(candidateState)) {
continue; continue;
} }
if (isEnclosed(level, candidate) || random.nextFloat() < 0.01f) { if (isEnclosed(level, candidate) || random.nextFloat() < 0.01f) {
@@ -219,8 +216,10 @@ public final class CavarynBileVeinFeature extends Feature<NoneFeatureConfigurati
return true; return true;
} }
private static boolean isVeinCandidate(BlockState state) { private static boolean isVeinCandidate(WorldGenLevel level, BlockPos pos) {
return state.blocksMotion() && !state.is(Blocks.BEDROCK) && state.getFluidState().isEmpty(); BlockState state = level.getBlockState(pos);
return state.blocksMotion() && !state.is(Blocks.BEDROCK) && state.getFluidState().isEmpty()
&& !CavarynFoliageGuard.isFoliageNearby(level, pos);
} }
private static Direction[] perpendiculars(Direction dir) { private static Direction[] perpendiculars(Direction dir) {
@@ -1,6 +1,7 @@
package com.craisinlord.antarchy.content.worldgen.cavaryn; package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.fluid.AntarchyFluidChecks;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import java.util.Optional; import java.util.Optional;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -56,6 +57,9 @@ public final class CavarynCreepvineFeature extends Feature<NoneFeatureConfigurat
if (!level.getBlockState(mutable).canBeReplaced()) { if (!level.getBlockState(mutable).canBeReplaced()) {
continue; continue;
} }
if (AntarchyFluidChecks.hasBileNearby(level, mutable, 1)) {
continue;
}
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos supportPos = mutable.relative(direction); BlockPos supportPos = mutable.relative(direction);
@@ -84,6 +88,9 @@ public final class CavarynCreepvineFeature extends Feature<NoneFeatureConfigurat
if (!existing.canBeReplaced() && !existing.is(vineBlock)) { if (!existing.canBeReplaced() && !existing.is(vineBlock)) {
break; break;
} }
if (AntarchyFluidChecks.hasBileNearby(level, vinePos, 1)) {
break;
}
BlockState vineState = createVineState(vineBlock, anchor.supportDirection()); BlockState vineState = createVineState(vineBlock, anchor.supportDirection());
if (vineState == null || !vineState.canSurvive(level, vinePos)) { if (vineState == null || !vineState.canSurvive(level, vinePos)) {
@@ -0,0 +1,38 @@
package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.content.block.HangingCreeprootsBlock;
import com.craisinlord.antarchy.content.block.MoltingVinesBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.VineBlock;
import net.minecraft.world.level.block.state.BlockState;
/**
* Bile always wins on placement, but once a vine/creeproots/molting-vine column already exists,
* bile carving and oozing must not eat the block it's anchored to — otherwise a later-generated
* neighboring chunk's bile cyst/vein can undermine foliage placed earlier and leave it floating
* or pop it as a dropped item.
*/
public final class CavarynFoliageGuard {
private CavarynFoliageGuard() {
}
public static boolean isFoliageNearby(LevelAccessor level, BlockPos center) {
if (isFoliage(level.getBlockState(center))) {
return true;
}
for (Direction direction : Direction.values()) {
if (isFoliage(level.getBlockState(center.relative(direction)))) {
return true;
}
}
return false;
}
private static boolean isFoliage(BlockState state) {
return state.getBlock() instanceof VineBlock
|| state.getBlock() instanceof HangingCreeprootsBlock
|| state.getBlock() instanceof MoltingVinesBlock;
}
}
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.block.MoltingVinesBlock; import com.craisinlord.antarchy.content.block.MoltingVinesBlock;
import com.craisinlord.antarchy.content.fluid.AntarchyFluidChecks;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import java.util.Optional; import java.util.Optional;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -61,6 +62,9 @@ public final class GroundMoltingVinesFeature extends Feature<NoneFeatureConfigur
if (!level.getBlockState(mutable).canBeReplaced()) { if (!level.getBlockState(mutable).canBeReplaced()) {
continue; continue;
} }
if (AntarchyFluidChecks.hasBileNearby(level, mutable, 1)) {
continue;
}
BlockPos belowPos = mutable.below(); BlockPos belowPos = mutable.below();
BlockState belowState = level.getBlockState(belowPos); BlockState belowState = level.getBlockState(belowPos);
if (!belowState.isFaceSturdy(level, belowPos, Direction.UP)) { if (!belowState.isFaceSturdy(level, belowPos, Direction.UP)) {
@@ -84,6 +88,9 @@ public final class GroundMoltingVinesFeature extends Feature<NoneFeatureConfigur
if (!existing.canBeReplaced()) { if (!existing.canBeReplaced()) {
break; break;
} }
if (AntarchyFluidChecks.hasBileNearby(level, mutable, 1)) {
break;
}
length++; length++;
mutable.move(0, 1, 0); mutable.move(0, 1, 0);
} }
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.block.HangingCreeprootsBlock; import com.craisinlord.antarchy.content.block.HangingCreeprootsBlock;
import com.craisinlord.antarchy.content.fluid.AntarchyFluidChecks;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import java.util.Optional; import java.util.Optional;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -55,6 +56,9 @@ public final class HangingCreeprootsFeature extends Feature<NoneFeatureConfigura
if (!level.getBlockState(mutable).canBeReplaced()) { if (!level.getBlockState(mutable).canBeReplaced()) {
continue; continue;
} }
if (AntarchyFluidChecks.hasBileNearby(level, mutable, 1)) {
continue;
}
BlockPos abovePos = mutable.above(); BlockPos abovePos = mutable.above();
BlockState aboveState = level.getBlockState(abovePos); BlockState aboveState = level.getBlockState(abovePos);
@@ -81,6 +85,9 @@ public final class HangingCreeprootsFeature extends Feature<NoneFeatureConfigura
if (!existing.canBeReplaced() && !existing.is(rootsBlock)) { if (!existing.canBeReplaced() && !existing.is(rootsBlock)) {
break; break;
} }
if (AntarchyFluidChecks.hasBileNearby(level, rootsPos, 1)) {
break;
}
int distance = Math.min(offset, 4); int distance = Math.min(offset, 4);
boolean bottom = offset == length - 1 || !level.getBlockState(rootsPos.below()).canBeReplaced(); boolean bottom = offset == length - 1 || !level.getBlockState(rootsPos.below()).canBeReplaced();
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.worldgen.cavaryn;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.block.MoltingVinesBlock; import com.craisinlord.antarchy.content.block.MoltingVinesBlock;
import com.craisinlord.antarchy.content.fluid.AntarchyFluidChecks;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import java.util.Optional; import java.util.Optional;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -60,6 +61,9 @@ public final class MoltingVinesFeature extends Feature<NoneFeatureConfiguration>
if (!level.getBlockState(mutable).canBeReplaced()) { if (!level.getBlockState(mutable).canBeReplaced()) {
continue; continue;
} }
if (AntarchyFluidChecks.hasBileNearby(level, mutable, 1)) {
continue;
}
BlockPos abovePos = mutable.above(); BlockPos abovePos = mutable.above();
BlockState aboveState = level.getBlockState(abovePos); BlockState aboveState = level.getBlockState(abovePos);
if (!aboveState.isFaceSturdy(level, abovePos, net.minecraft.core.Direction.DOWN)) { if (!aboveState.isFaceSturdy(level, abovePos, net.minecraft.core.Direction.DOWN)) {
@@ -83,6 +87,9 @@ public final class MoltingVinesFeature extends Feature<NoneFeatureConfiguration>
if (!existing.canBeReplaced()) { if (!existing.canBeReplaced()) {
break; break;
} }
if (AntarchyFluidChecks.hasBileNearby(level, mutable, 1)) {
break;
}
length++; length++;
mutable.move(0, -1, 0); mutable.move(0, -1, 0);
} }
@@ -349,7 +349,7 @@ public class PeachTreeFeature extends Feature<PeachTreeConfiguration> {
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
BlockPos current = queue.removeFirst(); BlockPos current = queue.removeFirst();
int currentDistance = distances.getOrDefault(current, 0); int currentDistance = distances.getOrDefault(current, 0);
if (currentDistance >= 6) { if (currentDistance >= PeachLeavesBlock.PEACH_MAX_DISTANCE) {
continue; continue;
} }
@@ -373,14 +373,14 @@ public class PeachTreeFeature extends Feature<PeachTreeConfiguration> {
continue; continue;
} }
IntegerProperty property = state.getBlock() instanceof PeachLeavesBlock ? LeavesBlock.DISTANCE : null; IntegerProperty property = state.getBlock() instanceof PeachLeavesBlock ? PeachLeavesBlock.PEACH_DISTANCE : null;
if (property == null) { if (property == null) {
continue; continue;
} }
int distance = Math.min(6, distances.getOrDefault(pos, 6)); int distance = Math.min(PeachLeavesBlock.PEACH_DECAY_DISTANCE, distances.getOrDefault(pos, PeachLeavesBlock.PEACH_DECAY_DISTANCE));
if (state.getValue(property) != distance) { if (state.getValue(property) != distance) {
setBlock(level, pos, state.setValue(property, distance)); setBlock(level, pos, PeachLeavesBlock.setPeachDistanceForWorldgen(state, distance));
} }
} }
} }
@@ -0,0 +1,153 @@
package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.minecart.AntimetalDismountHelper;
import com.craisinlord.antarchy.content.minecart.AntimetalMinecartAccess;
import com.craisinlord.antarchy.content.minecart.AntimetalMinecartPhysics;
import com.craisinlord.antarchy.content.minecart.AntimetalRailHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.level.block.BaseRailBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(AbstractMinecart.class)
public abstract class AbstractMinecartMixin implements AntimetalMinecartAccess {
@Unique
private static final EntityDataAccessor<Boolean> ANTARCHY$ON_ANTIMETAL_RAIL =
SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.BOOLEAN);
private static final int ANTARCHY$INVERTED_REFRESH_TICKS = 20;
@Unique
private boolean antarchy$antimetalActive;
@Unique
@Nullable
private BlockPos antarchy$antimetalRailPos;
@Unique
@Nullable
private BlockState antarchy$antimetalRailState;
@Shadow
protected abstract void moveAlongTrack(BlockPos pos, BlockState state);
@Inject(method = "defineSynchedData", at = @At("TAIL"))
private void antarchy$defineData(SynchedEntityData.Builder builder, CallbackInfo ci) {
builder.define(ANTARCHY$ON_ANTIMETAL_RAIL, false);
}
@Inject(method = "tick", at = @At("HEAD"))
private void antarchy$findAntimetalRail(CallbackInfo ci) {
AbstractMinecart self = (AbstractMinecart) (Object) this;
if (self.level().isClientSide()) {
return;
}
BlockPos cell = AntimetalMinecartPhysics.findCell(self.level(), self.getX(), self.getY(), self.getZ());
antarchy$antimetalActive = cell != null;
antarchy$antimetalRailPos = cell;
antarchy$antimetalRailState = cell != null ? self.level().getBlockState(cell) : null;
self.getEntityData().set(ANTARCHY$ON_ANTIMETAL_RAIL, antarchy$antimetalActive);
if (antarchy$antimetalActive) {
antarchy$applyInvertedGravity(self);
}
}
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/BaseRailBlock;isRail(Lnet/minecraft/world/level/block/state/BlockState;)Z"))
private boolean antarchy$redirectIsRail(BlockState state) {
if (antarchy$antimetalActive) {
return true;
}
return BaseRailBlock.isRail(state);
}
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/AbstractMinecart;moveAlongTrack(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V"))
private void antarchy$redirectMoveAlongTrack(AbstractMinecart self, BlockPos pos, BlockState state) {
if (antarchy$antimetalActive && antarchy$antimetalRailPos != null && antarchy$antimetalRailState != null) {
AntimetalMinecartPhysics.moveAlongTrack(self, antarchy$antimetalRailPos, antarchy$antimetalRailState);
} else {
this.moveAlongTrack(pos, state);
}
}
@Unique
private void antarchy$applyInvertedGravity(AbstractMinecart cart) {
for (Entity passenger : cart.getIndirectPassengers()) {
if (!(passenger instanceof LivingEntity living)) {
continue;
}
MobEffectInstance current = living.getEffect(AntarchyObjects.INVERTED_EFFECT.get());
if (current == null || current.getDuration() < 10) {
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), ANTARCHY$INVERTED_REFRESH_TICKS, 0, true, false, false));
}
}
}
@Inject(method = "getPassengerAttachmentPoint", at = @At("RETURN"), cancellable = true)
private void antarchy$mirrorPassengerAttachment(Entity passenger, EntityDimensions dimensions, float partialTick, CallbackInfoReturnable<Vec3> cir) {
if (this.antarchy$isOnAntimetalRail()) {
Vec3 original = cir.getReturnValue();
double mirroredY = 2.0D * AntimetalRailHelper.CART_MODEL_PIVOT_Y - original.y + 1.0D;
cir.setReturnValue(new Vec3(original.x, mirroredY, original.z));
}
}
@Inject(method = "getDismountLocationForPassenger", at = @At("HEAD"), cancellable = true)
private void antarchy$dismountBelowRail(LivingEntity passenger, CallbackInfoReturnable<Vec3> cir) {
if (this.antarchy$isOnAntimetalRail()) {
AbstractMinecart self = (AbstractMinecart) (Object) this;
cir.setReturnValue(AntimetalDismountHelper.findDismountPosition(self, passenger));
}
}
@Inject(method = "getPosOffs", at = @At("HEAD"), cancellable = true)
private void antarchy$sampleAntimetalPosOffs(double x, double y, double z, double offset, CallbackInfoReturnable<Vec3> cir) {
AbstractMinecart self = (AbstractMinecart) (Object) this;
if (this.antarchy$isOnAntimetalRail()) {
cir.setReturnValue(AntimetalMinecartPhysics.getPosOffs(self, x, y, z, offset));
}
}
@Inject(method = "getPos", at = @At("HEAD"), cancellable = true)
private void antarchy$sampleAntimetalPos(double x, double y, double z, CallbackInfoReturnable<Vec3> cir) {
AbstractMinecart self = (AbstractMinecart) (Object) this;
if (this.antarchy$isOnAntimetalRail()) {
cir.setReturnValue(AntimetalMinecartPhysics.getPos(self, x, y, z));
}
}
@Override
public boolean antarchy$isOnAntimetalRail() {
return ((AbstractMinecart) (Object) this).getEntityData().get(ANTARCHY$ON_ANTIMETAL_RAIL);
}
@Override
public void antarchy$setOnAntimetalRail(boolean value) {
((AbstractMinecart) (Object) this).getEntityData().set(ANTARCHY$ON_ANTIMETAL_RAIL, value);
}
@Override
@Nullable
public BlockPos antarchy$getAntimetalRailPos() {
return antarchy$antimetalRailPos;
}
@Override
public void antarchy$setAntimetalRailPos(@Nullable BlockPos pos) {
antarchy$antimetalRailPos = pos;
}
}
@@ -0,0 +1,20 @@
package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.block.BluestoneComparatorBlock;
import com.craisinlord.antarchy.content.block.BluestoneRepeaterBlock;
import net.minecraft.world.level.block.DiodeBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DiodeBlock.class)
public class DiodeBlockMixin {
@Inject(method = "isDiode", at = @At("HEAD"), cancellable = true)
private static void antarchy$ignoreBluestoneDiodes(BlockState state, CallbackInfoReturnable<Boolean> cir) {
if (state.getBlock() instanceof BluestoneRepeaterBlock || state.getBlock() instanceof BluestoneComparatorBlock) {
cir.setReturnValue(false);
}
}
}
@@ -0,0 +1,58 @@
package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.block.AbstractAntimetalRailBlock;
import com.craisinlord.antarchy.content.minecart.AntimetalRailHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.MinecartItem;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(MinecartItem.class)
public abstract class MinecartItemMixin {
@Shadow
@Final
AbstractMinecart.Type type;
@Inject(method = "useOn", at = @At("HEAD"), cancellable = true)
private void antarchy$placeOnAntimetalRail(UseOnContext context, CallbackInfoReturnable<InteractionResult> cir) {
Level level = context.getLevel();
BlockPos pos = context.getClickedPos();
BlockState state = level.getBlockState(pos);
if (!(state.getBlock() instanceof AbstractAntimetalRailBlock)) {
return;
}
if (level.isClientSide()) {
cir.setReturnValue(InteractionResult.SUCCESS);
return;
}
ServerLevel serverLevel = (ServerLevel) level;
double x = pos.getX() + 0.5D;
double y = AntimetalRailHelper.attachY(pos.getY(), 0);
double z = pos.getZ() + 0.5D;
ItemStack stack = context.getItemInHand();
Player player = context.getPlayer();
AbstractMinecart cart = AbstractMinecart.createMinecart(serverLevel, x, y, z, this.type, stack, player);
if (cart != null) {
serverLevel.addFreshEntity(cart);
serverLevel.gameEvent(GameEvent.ENTITY_PLACE, pos, GameEvent.Context.of(player));
if (player == null || !player.getAbilities().instabuild) {
stack.shrink(1);
}
}
cir.setReturnValue(InteractionResult.sidedSuccess(level.isClientSide()));
}
}
@@ -1,9 +1,18 @@
package com.craisinlord.antarchy.mixins; package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.block.BluestoneBlock;
import com.craisinlord.antarchy.content.block.BluestoneComparatorBlock;
import com.craisinlord.antarchy.content.block.BluestoneRepeaterBlock;
import com.craisinlord.antarchy.content.block.BluestoneTorchBlock;
import com.craisinlord.antarchy.content.block.BluestoneWireBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.RedStoneWireBlock; import net.minecraft.world.level.block.RedStoneWireBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.RedstoneSide;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@@ -13,15 +22,77 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class RedStoneWireBlockMixin { public class RedStoneWireBlockMixin {
@Inject(method = "shouldConnectTo(Lnet/minecraft/world/level/block/state/BlockState;)Z", at = @At("HEAD"), cancellable = true) @Inject(method = "shouldConnectTo(Lnet/minecraft/world/level/block/state/BlockState;)Z", at = @At("HEAD"), cancellable = true)
private static void antarchy$rejectBluestone(BlockState state, CallbackInfoReturnable<Boolean> cir) { private static void antarchy$rejectBluestone(BlockState state, CallbackInfoReturnable<Boolean> cir) {
if (state.is(AntarchyTags.Blocks.BLUESTONE_COMPONENTS)) { if (antarchy$isBluestoneBlock(state)) {
cir.setReturnValue(false); cir.setReturnValue(false);
} }
} }
@Inject(method = "shouldConnectTo(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/Direction;)Z", at = @At("HEAD"), cancellable = true) @Inject(method = "shouldConnectTo(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/Direction;)Z", at = @At("HEAD"), cancellable = true)
private static void antarchy$rejectBluestone(BlockState state, Direction direction, CallbackInfoReturnable<Boolean> cir) { private static void antarchy$rejectBluestone(BlockState state, Direction direction, CallbackInfoReturnable<Boolean> cir) {
if (state.is(AntarchyTags.Blocks.BLUESTONE_COMPONENTS)) { if (antarchy$isBluestoneBlock(state)) {
cir.setReturnValue(false); cir.setReturnValue(false);
} }
} }
@Inject(method = "getConnectingSide", at = @At("HEAD"), cancellable = true)
private void antarchy$blockBluestoneSide(BlockGetter level, BlockPos pos, Direction direction, CallbackInfoReturnable<RedstoneSide> cir) {
BlockPos sidePos = pos.relative(direction);
if (antarchy$isBluestoneConnection(level, sidePos)) {
cir.setReturnValue(RedstoneSide.NONE);
}
}
@Inject(method = "calculateTargetStrength", at = @At("HEAD"), cancellable = true)
private void antarchy$ignoreBluestonePower(Level level, BlockPos pos, CallbackInfoReturnable<Integer> cir) {
cir.setReturnValue(this.antarchy$getReceivedRedstonePower(level, pos));
}
private int antarchy$getReceivedRedstonePower(Level level, BlockPos pos) {
int signal = 0;
for (Direction direction : Direction.values()) {
BlockPos sidePos = pos.relative(direction);
BlockState sideState = level.getBlockState(sidePos);
signal = Math.max(signal, this.antarchy$getSignalFromState(level, sidePos, sideState, direction));
if (signal >= 15) {
return 15;
}
BlockPos abovePos = sidePos.above();
BlockPos belowPos = sidePos.below();
BlockState aboveState = level.getBlockState(abovePos);
BlockState belowState = level.getBlockState(belowPos);
if (sideState.isRedstoneConductor(level, sidePos)) {
if (!aboveState.isRedstoneConductor(level, abovePos)) {
signal = Math.max(signal, this.antarchy$getSignalFromState(level, abovePos, aboveState, direction));
}
} else {
signal = Math.max(signal, this.antarchy$getSignalFromState(level, belowPos, belowState, direction));
}
if (signal >= 15) {
return 15;
}
}
return signal;
}
private int antarchy$getSignalFromState(Level level, BlockPos pos, BlockState state, Direction direction) {
if (antarchy$isBluestoneBlock(state)) {
return 0;
}
return state.getSignal(level, pos, direction);
}
private static boolean antarchy$isBluestoneBlock(BlockState state) {
return state.is(AntarchyTags.Blocks.BLUESTONE_COMPONENTS)
|| state.getBlock() instanceof BluestoneWireBlock
|| state.getBlock() instanceof BluestoneRepeaterBlock
|| state.getBlock() instanceof BluestoneComparatorBlock
|| state.getBlock() instanceof BluestoneTorchBlock
|| state.getBlock() instanceof BluestoneBlock;
}
private static boolean antarchy$isBluestoneConnection(BlockGetter level, BlockPos pos) {
return antarchy$isBluestoneBlock(level.getBlockState(pos))
|| antarchy$isBluestoneBlock(level.getBlockState(pos.above()))
|| antarchy$isBluestoneBlock(level.getBlockState(pos.below()));
}
} }
@@ -0,0 +1,37 @@
package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.minecart.AntimetalMinecartAccess;
import com.craisinlord.antarchy.content.minecart.AntimetalRailHelper;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.MinecartRenderer;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecartRenderer.class)
public abstract class AbstractMinecartRendererMixin<T extends AbstractMinecart> {
private static final double ANTARCHY$FLIP_PIVOT_Y = AntimetalRailHelper.CART_MODEL_PIVOT_Y;
private static final double ANTARCHY$MODEL_DROP = 0.1875D;
@Inject(method = "render(Lnet/minecraft/world/entity/vehicle/AbstractMinecart;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At("HEAD"))
private void antarchy$flipHead(T entity, float yaw, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
if (entity instanceof AntimetalMinecartAccess access && access.antarchy$isOnAntimetalRail()) {
poseStack.pushPose();
poseStack.translate(0.0D, -ANTARCHY$MODEL_DROP, 0.0D);
poseStack.translate(0.0D, ANTARCHY$FLIP_PIVOT_Y, 0.0D);
poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F));
poseStack.translate(0.0D, -ANTARCHY$FLIP_PIVOT_Y, 0.0D);
}
}
@Inject(method = "render(Lnet/minecraft/world/entity/vehicle/AbstractMinecart;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At("TAIL"))
private void antarchy$flipTail(T entity, float yaw, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
if (entity instanceof AntimetalMinecartAccess access && access.antarchy$isOnAntimetalRail()) {
poseStack.popPose();
}
}
}
@@ -0,0 +1,22 @@
package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.minecart.AntimetalMinecartAccess;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Entity.class)
public abstract class EntityLightProbeMixin {
@Inject(method = "getLightProbePosition", at = @At("RETURN"), cancellable = true)
private void antarchy$mirrorLightProbe(float partialTick, CallbackInfoReturnable<Vec3> cir) {
if ((Object) this instanceof AntimetalMinecartAccess access && access.antarchy$isOnAntimetalRail()) {
Entity self = (Entity) (Object) this;
Vec3 original = cir.getReturnValue();
double mirroredY = original.y - 2.0D * self.getEyeHeight();
cir.setReturnValue(new Vec3(original.x, mirroredY, original.z));
}
}
}
@@ -4,6 +4,7 @@
"plugin": "com.craisinlord.antarchy.mixins.AntarchyMixinPlugin", "plugin": "com.craisinlord.antarchy.mixins.AntarchyMixinPlugin",
"compatibilityLevel": "JAVA_21", "compatibilityLevel": "JAVA_21",
"mixins": [ "mixins": [
"AbstractMinecartMixin",
"AccessorRangedAttribute", "AccessorRangedAttribute",
"AmericanFoodConsumeMixin", "AmericanFoodConsumeMixin",
"AmericanFoodNameMixin", "AmericanFoodNameMixin",
@@ -12,6 +13,7 @@
"DreamFireBlockMixin", "DreamFireBlockMixin",
"DreamSandFallingSpeedMixin", "DreamSandFallingSpeedMixin",
"DreamSandLowGravityMixin", "DreamSandLowGravityMixin",
"DiodeBlockMixin",
"FarChunkSetBlockWarningMixin", "FarChunkSetBlockWarningMixin",
"FireVisualBaseFireBlockMixin", "FireVisualBaseFireBlockMixin",
"FireVisualEntityMixin", "FireVisualEntityMixin",
@@ -22,6 +24,7 @@
"GlowVinesUnderLeavesMixin", "GlowVinesUnderLeavesMixin",
"MantisClawWallClimbMixin", "MantisClawWallClimbMixin",
"MilkBucketSizeResetMixin", "MilkBucketSizeResetMixin",
"MinecartItemMixin",
"GoopedStepSoundMixin", "GoopedStepSoundMixin",
"ExperimentalSettingsLevelSummaryMixin", "ExperimentalSettingsLevelSummaryMixin",
"NightmareSwordDamageMixin", "NightmareSwordDamageMixin",
@@ -65,6 +68,8 @@
"multipart.EntityMultipartLifecycleMixin" "multipart.EntityMultipartLifecycleMixin"
], ],
"client": [ "client": [
"client.AbstractMinecartRendererMixin",
"client.EntityLightProbeMixin",
"client.CustomBossBarMixin", "client.CustomBossBarMixin",
"client.CavarynSkyMixin", "client.CavarynSkyMixin",
"client.CavarynHordeFogMixin", "client.CavarynHordeFogMixin",
@@ -0,0 +1,46 @@
{
"variants": {
"shape=north_south,powered=false": {
"model": "antarchy:block/antimetal_activator_rail"
},
"shape=east_west,powered=false": {
"model": "antarchy:block/antimetal_activator_rail",
"y": 90
},
"shape=ascending_north,powered=false": {
"model": "antarchy:block/antimetal_activator_rail_raised_ne"
},
"shape=ascending_east,powered=false": {
"model": "antarchy:block/antimetal_activator_rail_raised_ne",
"y": 90
},
"shape=ascending_south,powered=false": {
"model": "antarchy:block/antimetal_activator_rail_raised_sw"
},
"shape=ascending_west,powered=false": {
"model": "antarchy:block/antimetal_activator_rail_raised_sw",
"y": 90
},
"shape=north_south,powered=true": {
"model": "antarchy:block/antimetal_activator_rail_on"
},
"shape=east_west,powered=true": {
"model": "antarchy:block/antimetal_activator_rail_on",
"y": 90
},
"shape=ascending_north,powered=true": {
"model": "antarchy:block/antimetal_activator_rail_raised_on_ne"
},
"shape=ascending_east,powered=true": {
"model": "antarchy:block/antimetal_activator_rail_raised_on_ne",
"y": 90
},
"shape=ascending_south,powered=true": {
"model": "antarchy:block/antimetal_activator_rail_raised_on_sw"
},
"shape=ascending_west,powered=true": {
"model": "antarchy:block/antimetal_activator_rail_raised_on_sw",
"y": 90
}
}
}
@@ -0,0 +1,46 @@
{
"variants": {
"shape=north_south,powered=false": {
"model": "antarchy:block/antimetal_detector_rail"
},
"shape=east_west,powered=false": {
"model": "antarchy:block/antimetal_detector_rail",
"y": 90
},
"shape=ascending_north,powered=false": {
"model": "antarchy:block/antimetal_detector_rail_raised_ne"
},
"shape=ascending_east,powered=false": {
"model": "antarchy:block/antimetal_detector_rail_raised_ne",
"y": 90
},
"shape=ascending_south,powered=false": {
"model": "antarchy:block/antimetal_detector_rail_raised_sw"
},
"shape=ascending_west,powered=false": {
"model": "antarchy:block/antimetal_detector_rail_raised_sw",
"y": 90
},
"shape=north_south,powered=true": {
"model": "antarchy:block/antimetal_detector_rail_on"
},
"shape=east_west,powered=true": {
"model": "antarchy:block/antimetal_detector_rail_on",
"y": 90
},
"shape=ascending_north,powered=true": {
"model": "antarchy:block/antimetal_detector_rail_raised_on_ne"
},
"shape=ascending_east,powered=true": {
"model": "antarchy:block/antimetal_detector_rail_raised_on_ne",
"y": 90
},
"shape=ascending_south,powered=true": {
"model": "antarchy:block/antimetal_detector_rail_raised_on_sw"
},
"shape=ascending_west,powered=true": {
"model": "antarchy:block/antimetal_detector_rail_raised_on_sw",
"y": 90
}
}
}
@@ -0,0 +1,46 @@
{
"variants": {
"shape=north_south,powered=false": {
"model": "antarchy:block/antimetal_powered_rail"
},
"shape=east_west,powered=false": {
"model": "antarchy:block/antimetal_powered_rail",
"y": 90
},
"shape=ascending_north,powered=false": {
"model": "antarchy:block/antimetal_powered_rail_raised_ne"
},
"shape=ascending_east,powered=false": {
"model": "antarchy:block/antimetal_powered_rail_raised_ne",
"y": 90
},
"shape=ascending_south,powered=false": {
"model": "antarchy:block/antimetal_powered_rail_raised_sw"
},
"shape=ascending_west,powered=false": {
"model": "antarchy:block/antimetal_powered_rail_raised_sw",
"y": 90
},
"shape=north_south,powered=true": {
"model": "antarchy:block/antimetal_powered_rail_on"
},
"shape=east_west,powered=true": {
"model": "antarchy:block/antimetal_powered_rail_on",
"y": 90
},
"shape=ascending_north,powered=true": {
"model": "antarchy:block/antimetal_powered_rail_raised_on_ne"
},
"shape=ascending_east,powered=true": {
"model": "antarchy:block/antimetal_powered_rail_raised_on_ne",
"y": 90
},
"shape=ascending_south,powered=true": {
"model": "antarchy:block/antimetal_powered_rail_raised_on_sw"
},
"shape=ascending_west,powered=true": {
"model": "antarchy:block/antimetal_powered_rail_raised_on_sw",
"y": 90
}
}
}
@@ -0,0 +1,40 @@
{
"variants": {
"shape=north_south": {
"model": "antarchy:block/antimetal_rail"
},
"shape=east_west": {
"model": "antarchy:block/antimetal_rail",
"y": 90
},
"shape=ascending_north": {
"model": "antarchy:block/antimetal_rail_raised_ne"
},
"shape=ascending_east": {
"model": "antarchy:block/antimetal_rail_raised_ne",
"y": 90
},
"shape=ascending_south": {
"model": "antarchy:block/antimetal_rail_raised_sw"
},
"shape=ascending_west": {
"model": "antarchy:block/antimetal_rail_raised_sw",
"y": 90
},
"shape=south_east": {
"model": "antarchy:block/antimetal_rail_corner"
},
"shape=south_west": {
"model": "antarchy:block/antimetal_rail_corner",
"y": 90
},
"shape=north_west": {
"model": "antarchy:block/antimetal_rail_corner",
"y": 180
},
"shape=north_east": {
"model": "antarchy:block/antimetal_rail_corner",
"y": 270
}
}
}
@@ -2,6 +2,7 @@
"multipart": [ "multipart": [
{ {
"when": { "when": {
"delay": "1",
"facing": "north", "facing": "north",
"powered": "false" "powered": "false"
}, },
@@ -11,6 +12,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "east", "facing": "east",
"powered": "false" "powered": "false"
}, },
@@ -21,6 +23,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "south", "facing": "south",
"powered": "false" "powered": "false"
}, },
@@ -31,6 +34,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "west", "facing": "west",
"powered": "false" "powered": "false"
}, },
@@ -41,6 +45,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "north", "facing": "north",
"powered": "true" "powered": "true"
}, },
@@ -50,6 +55,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "east", "facing": "east",
"powered": "true" "powered": "true"
}, },
@@ -60,6 +66,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "south", "facing": "south",
"powered": "true" "powered": "true"
}, },
@@ -70,6 +77,7 @@
}, },
{ {
"when": { "when": {
"delay": "1",
"facing": "west", "facing": "west",
"powered": "true" "powered": "true"
}, },
@@ -77,6 +85,303 @@
"model": "antarchy:block/bluestone_repeater_on", "model": "antarchy:block/bluestone_repeater_on",
"y": 270 "y": 270
} }
},
{
"when": {
"delay": "2",
"facing": "north",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2"
}
},
{
"when": {
"delay": "2",
"facing": "east",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2",
"y": 90
}
},
{
"when": {
"delay": "2",
"facing": "south",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2",
"y": 180
}
},
{
"when": {
"delay": "2",
"facing": "west",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2",
"y": 270
}
},
{
"when": {
"delay": "2",
"facing": "north",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2_on"
}
},
{
"when": {
"delay": "2",
"facing": "east",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2_on",
"y": 90
}
},
{
"when": {
"delay": "2",
"facing": "south",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2_on",
"y": 180
}
},
{
"when": {
"delay": "2",
"facing": "west",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay2_on",
"y": 270
}
},
{
"when": {
"delay": "3",
"facing": "north",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3"
}
},
{
"when": {
"delay": "3",
"facing": "east",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3",
"y": 90
}
},
{
"when": {
"delay": "3",
"facing": "south",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3",
"y": 180
}
},
{
"when": {
"delay": "3",
"facing": "west",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3",
"y": 270
}
},
{
"when": {
"delay": "3",
"facing": "north",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3_on"
}
},
{
"when": {
"delay": "3",
"facing": "east",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3_on",
"y": 90
}
},
{
"when": {
"delay": "3",
"facing": "south",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3_on",
"y": 180
}
},
{
"when": {
"delay": "3",
"facing": "west",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay3_on",
"y": 270
}
},
{
"when": {
"delay": "4",
"facing": "north",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4"
}
},
{
"when": {
"delay": "4",
"facing": "east",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4",
"y": 90
}
},
{
"when": {
"delay": "4",
"facing": "south",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4",
"y": 180
}
},
{
"when": {
"delay": "4",
"facing": "west",
"powered": "false"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4",
"y": 270
}
},
{
"when": {
"delay": "4",
"facing": "north",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4_on"
}
},
{
"when": {
"delay": "4",
"facing": "east",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4_on",
"y": 90
}
},
{
"when": {
"delay": "4",
"facing": "south",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4_on",
"y": 180
}
},
{
"when": {
"delay": "4",
"facing": "west",
"powered": "true"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_delay4_on",
"y": 270
}
},
{
"when": {
"locked": "true",
"facing": "north"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_lock"
}
},
{
"when": {
"locked": "true",
"facing": "east"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_lock",
"y": 90
}
},
{
"when": {
"locked": "true",
"facing": "south"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_lock",
"y": 180
}
},
{
"when": {
"locked": "true",
"facing": "west"
},
"apply": {
"model": "antarchy:block/bluestone_repeater_lock",
"y": 270
}
} }
] ]
} }
@@ -1,10 +1,84 @@
{ {
"variants": { "variants": {
"lit=false": { "face=ceiling,facing=north,lit=false": {
"model": "antarchy:block/bluestone_torch_off" "model": "antarchy:block/bluestone_torch_off"
}, },
"lit=true": { "face=ceiling,facing=east,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=ceiling,facing=south,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=ceiling,facing=west,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=floor,facing=north,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=floor,facing=east,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=floor,facing=south,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=floor,facing=west,lit=false": {
"model": "antarchy:block/bluestone_torch_off"
},
"face=ceiling,facing=north,lit=true": {
"model": "antarchy:block/bluestone_torch" "model": "antarchy:block/bluestone_torch"
},
"face=ceiling,facing=east,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=ceiling,facing=south,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=ceiling,facing=west,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=floor,facing=north,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=floor,facing=east,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=floor,facing=south,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=floor,facing=west,lit=true": {
"model": "antarchy:block/bluestone_torch"
},
"face=wall,facing=north,lit=false": {
"model": "antarchy:block/bluestone_wall_torch_off",
"y": 270
},
"face=wall,facing=east,lit=false": {
"model": "antarchy:block/bluestone_wall_torch_off",
"y": 0
},
"face=wall,facing=south,lit=false": {
"model": "antarchy:block/bluestone_wall_torch_off",
"y": 90
},
"face=wall,facing=west,lit=false": {
"model": "antarchy:block/bluestone_wall_torch_off",
"y": 180
},
"face=wall,facing=north,lit=true": {
"model": "antarchy:block/bluestone_wall_torch",
"y": 270
},
"face=wall,facing=east,lit=true": {
"model": "antarchy:block/bluestone_wall_torch",
"y": 0
},
"face=wall,facing=south,lit=true": {
"model": "antarchy:block/bluestone_wall_torch",
"y": 90
},
"face=wall,facing=west,lit=true": {
"model": "antarchy:block/bluestone_wall_torch",
"y": 180
} }
} }
} }
@@ -4,6 +4,32 @@
"apply": { "apply": {
"model": "antarchy:block/bluestone_wire_dot", "model": "antarchy:block/bluestone_wire_dot",
"x": 180 "x": 180
},
"when": {
"OR": [
{
"east": "none",
"north": "none",
"south": "none",
"west": "none"
},
{
"east": "side|down",
"north": "side|down"
},
{
"east": "side|down",
"south": "side|down"
},
{
"south": "side|down",
"west": "side|down"
},
{
"north": "side|down",
"west": "side|down"
}
]
} }
}, },
{ {
@@ -11,17 +37,9 @@
"north": "side|down" "north": "side|down"
}, },
"apply": { "apply": {
"model": "antarchy:block/bluestone_wire_line0", "model": "antarchy:block/bluestone_wire_side0",
"x": 180 "x": 180,
} "y": 180
},
{
"when": {
"east": "side|down"
},
"apply": {
"model": "antarchy:block/bluestone_wire_line1",
"x": 180
} }
}, },
{ {
@@ -29,20 +47,70 @@
"south": "side|down" "south": "side|down"
}, },
"apply": { "apply": {
"model": "antarchy:block/bluestone_wire_line0", "model": "antarchy:block/bluestone_wire_side_alt0",
"x": 180, "x": 180,
"y": 180 "y": 180
} }
}, },
{
"when": {
"east": "side|down"
},
"apply": {
"model": "antarchy:block/bluestone_wire_side_alt1",
"x": 180,
"y": 90
}
},
{ {
"when": { "when": {
"west": "side|down" "west": "side|down"
}, },
"apply": { "apply": {
"model": "antarchy:block/bluestone_wire_line1", "model": "antarchy:block/bluestone_wire_side1",
"x": 180,
"y": 90
}
},
{
"when": {
"north": "down"
},
"apply": {
"model": "antarchy:block/bluestone_wire_down",
"x": 180, "x": 180,
"y": 180 "y": 180
} }
},
{
"when": {
"east": "down"
},
"apply": {
"model": "antarchy:block/bluestone_wire_down",
"x": 180,
"y": 90
}
},
{
"when": {
"south": "down"
},
"apply": {
"model": "antarchy:block/bluestone_wire_down",
"x": 180,
"y": 0
}
},
{
"when": {
"west": "down"
},
"apply": {
"model": "antarchy:block/bluestone_wire_down",
"x": 180,
"y": 270
}
} }
] ]
} }
@@ -0,0 +1,118 @@
{
"variants": {
"face=ceiling,facing=east,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"x": 180,
"y": 270
},
"face=ceiling,facing=east,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"x": 180,
"y": 270
},
"face=ceiling,facing=north,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"x": 180,
"y": 180
},
"face=ceiling,facing=north,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"x": 180,
"y": 180
},
"face=ceiling,facing=south,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"x": 180
},
"face=ceiling,facing=south,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"x": 180
},
"face=ceiling,facing=west,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"x": 180,
"y": 90
},
"face=ceiling,facing=west,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"x": 180,
"y": 90
},
"face=floor,facing=east,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"y": 90
},
"face=floor,facing=east,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"y": 90
},
"face=floor,facing=north,powered=false": {
"model": "antarchy:block/polished_nyxite_button"
},
"face=floor,facing=north,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed"
},
"face=floor,facing=south,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"y": 180
},
"face=floor,facing=south,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"y": 180
},
"face=floor,facing=west,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"y": 270
},
"face=floor,facing=west,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"y": 270
},
"face=wall,facing=east,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"uvlock": true,
"x": 90,
"y": 90
},
"face=wall,facing=east,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"uvlock": true,
"x": 90,
"y": 90
},
"face=wall,facing=north,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"uvlock": true,
"x": 90
},
"face=wall,facing=north,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"uvlock": true,
"x": 90
},
"face=wall,facing=south,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"uvlock": true,
"x": 90,
"y": 180
},
"face=wall,facing=south,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"uvlock": true,
"x": 90,
"y": 180
},
"face=wall,facing=west,powered=false": {
"model": "antarchy:block/polished_nyxite_button",
"uvlock": true,
"x": 90,
"y": 270
},
"face=wall,facing=west,powered=true": {
"model": "antarchy:block/polished_nyxite_button_pressed",
"uvlock": true,
"x": 90,
"y": 270
}
}
}
@@ -0,0 +1,18 @@
{
"variants": {
"ceiling=false,powered=false": {
"model": "antarchy:block/polished_nyxite_pressure_plate"
},
"ceiling=false,powered=true": {
"model": "antarchy:block/polished_nyxite_pressure_plate_down"
},
"ceiling=true,powered=false": {
"model": "antarchy:block/polished_nyxite_pressure_plate",
"x": 180
},
"ceiling=true,powered=true": {
"model": "antarchy:block/polished_nyxite_pressure_plate_down",
"x": 180
}
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "antarchy:item/bluestone_wire"
}
}
@@ -84,6 +84,8 @@
"block.antarchy.polished_nyxite_stairs": "Polished Nyxite Stairs", "block.antarchy.polished_nyxite_stairs": "Polished Nyxite Stairs",
"block.antarchy.polished_nyxite_slab": "Polished Nyxite Slab", "block.antarchy.polished_nyxite_slab": "Polished Nyxite Slab",
"block.antarchy.polished_nyxite_wall": "Polished Nyxite Wall", "block.antarchy.polished_nyxite_wall": "Polished Nyxite Wall",
"block.antarchy.polished_nyxite_pressure_plate": "Polished Nyxite Pressure Plate",
"block.antarchy.polished_nyxite_button": "Polished Nyxite Button",
"block.antarchy.nyxite_brick_stairs": "Nyxite Brick Stairs", "block.antarchy.nyxite_brick_stairs": "Nyxite Brick Stairs",
"block.antarchy.nyxite_brick_slab": "Nyxite Brick Slab", "block.antarchy.nyxite_brick_slab": "Nyxite Brick Slab",
"block.antarchy.nyxite_brick_wall": "Nyxite Brick Wall", "block.antarchy.nyxite_brick_wall": "Nyxite Brick Wall",
@@ -97,6 +99,10 @@
"block.antarchy.antimetal": "Antimetal", "block.antarchy.antimetal": "Antimetal",
"block.antarchy.polished_antimetal": "Polished Antimetal", "block.antarchy.polished_antimetal": "Polished Antimetal",
"block.antarchy.antimetal_scaffolding": "Antimetal Scaffolding", "block.antarchy.antimetal_scaffolding": "Antimetal Scaffolding",
"block.antarchy.antimetal_rail": "Antimetal Rail",
"block.antarchy.antimetal_powered_rail": "Antimetal Powered Rail",
"block.antarchy.antimetal_detector_rail": "Antimetal Detector Rail",
"block.antarchy.antimetal_activator_rail": "Antimetal Activator Rail",
"block.antarchy.cornea_stalk": "Cornea Stalk", "block.antarchy.cornea_stalk": "Cornea Stalk",
"block.antarchy.corn_crop": "Corn Crop", "block.antarchy.corn_crop": "Corn Crop",
"block.antarchy.dream_torch": "Dream Torch", "block.antarchy.dream_torch": "Dream Torch",
@@ -158,6 +164,7 @@
"block.antarchy.titanium_bars": "Titanium Bars", "block.antarchy.titanium_bars": "Titanium Bars",
"tooltip.antarchy.signal_saving_bulb": "Toggles on/off. Has light level equal to the signal strength stored on it.", "tooltip.antarchy.signal_saving_bulb": "Toggles on/off. Has light level equal to the signal strength stored on it.",
"tooltip.antarchy.bluestone_placement": "Places below blocks", "tooltip.antarchy.bluestone_placement": "Places below blocks",
"tooltip.antarchy.ceiling_compatible_placement": "Can also be placed on ceilings",
"block.antarchy.bile": "Bile", "block.antarchy.bile": "Bile",
"block.antarchy.ichor": "Ichor", "block.antarchy.ichor": "Ichor",
"block.antarchy.antiwater": "Antiwater", "block.antarchy.antiwater": "Antiwater",
@@ -308,6 +315,10 @@
"item.antarchy.antimetal": "Antimetal", "item.antarchy.antimetal": "Antimetal",
"item.antarchy.polished_antimetal": "Polished Antimetal", "item.antarchy.polished_antimetal": "Polished Antimetal",
"item.antarchy.antimetal_scaffolding": "Antimetal Scaffolding", "item.antarchy.antimetal_scaffolding": "Antimetal Scaffolding",
"item.antarchy.antimetal_rail": "Antimetal Rail",
"item.antarchy.antimetal_powered_rail": "Antimetal Powered Rail",
"item.antarchy.antimetal_detector_rail": "Antimetal Detector Rail",
"item.antarchy.antimetal_activator_rail": "Antimetal Activator Rail",
"item.antarchy.ouranwood_acorn": "Ouranwood Acorn", "item.antarchy.ouranwood_acorn": "Ouranwood Acorn",
"item.antarchy.ouranwood_boat": "Ouranwood Boat", "item.antarchy.ouranwood_boat": "Ouranwood Boat",
"item.antarchy.ouranwood_chest_boat": "Ouranwood Chest Boat", "item.antarchy.ouranwood_chest_boat": "Ouranwood Chest Boat",
@@ -869,6 +880,7 @@
"biome.antarchy.cloud_sea": "Cloud Sea", "biome.antarchy.cloud_sea": "Cloud Sea",
"block.antarchy.wild_corn": "Wild Corn", "block.antarchy.wild_corn": "Wild Corn",
"trim_material.antarchy.blood_crystal": "Blood Crystal", "trim_material.antarchy.blood_crystal": "Blood Crystal",
"trim_material.antarchy.bluestone": "Bluestone",
"trim_material.antarchy.nightmare_scale": "Nightmare Scale", "trim_material.antarchy.nightmare_scale": "Nightmare Scale",
"trim_material.antarchy.uranium": "Uranium", "trim_material.antarchy.uranium": "Uranium",
"trim_material.antarchy.titanium": "Titanium", "trim_material.antarchy.titanium": "Titanium",
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_activator_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_activator_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_activator_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_activator_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_activator_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_activator_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_detector_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_detector_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_detector_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_detector_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_detector_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_detector_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_powered_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_powered_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_powered_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_powered_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_powered_rail_on" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_powered_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_flat",
"textures": { "rail": "antarchy:block/antimetal/antimetal_rail_corner" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_ne",
"textures": { "rail": "antarchy:block/antimetal/antimetal_rail" }
}
@@ -0,0 +1,4 @@
{
"parent": "antarchy:block/template_antimetal_rail_raised_sw",
"textures": { "rail": "antarchy:block/antimetal/antimetal_rail" }
}
@@ -21,36 +21,36 @@
} }
}, },
{ {
"from": [4, 9, 11], "from": [4, 9, 2],
"to": [6, 14, 13], "to": [6, 14, 4],
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 6, 9, 11], "texture": "#unlit" } "east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
} }
}, },
{ {
"from": [10, 9, 11], "from": [10, 9, 2],
"to": [12, 14, 13], "to": [12, 14, 4],
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 6, 9, 11], "texture": "#unlit" } "east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
} }
}, },
{ {
"from": [7, 11, 2], "from": [7, 11, 11],
"to": [9, 14, 4], "to": [9, 14, 13],
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "north": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "south": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "west": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 6, 9, 9], "texture": "#unlit" } "east": { "uv": [7, 9, 9, 6], "texture": "#unlit" }
} }
} }
] ]
@@ -21,39 +21,39 @@
} }
}, },
{ {
"from": [4, 9, 11], "from": [4, 9, 2],
"to": [6, 14, 13], "to": [6, 14, 4],
"shade": false, "shade": false,
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 6, 9, 11], "texture": "#lit" } "east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
} }
}, },
{ {
"from": [10, 9, 11], "from": [10, 9, 2],
"to": [12, 14, 13], "to": [12, 14, 4],
"shade": false, "shade": false,
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 6, 9, 11], "texture": "#lit" } "east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
} }
}, },
{ {
"from": [7, 11, 2], "from": [7, 11, 11],
"to": [9, 14, 4], "to": [9, 14, 13],
"shade": false, "shade": false,
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "north": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "south": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "west": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 6, 9, 9], "texture": "#unlit" } "east": { "uv": [7, 9, 9, 6], "texture": "#unlit" }
} }
} }
] ]
@@ -1,3 +1,58 @@
{ {
"parent": "antarchy:block/bluestone_comparator" "ambientocclusion": false,
"textures": {
"particle": "antarchy:block/bluestone/bluestone_comparator",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_comparator",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [4, 9, 2],
"to": [6, 14, 4],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
}
},
{
"from": [10, 9, 2],
"to": [12, 14, 4],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
}
},
{
"from": [7, 11, 11],
"to": [9, 14, 13],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#lit" }
}
}
]
} }
@@ -1,3 +1,60 @@
{ {
"parent": "antarchy:block/bluestone_comparator_on" "ambientocclusion": false,
"textures": {
"particle": "antarchy:block/bluestone/bluestone_comparator_on",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_comparator_on",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [4, 9, 2],
"to": [6, 14, 4],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
}
},
{
"from": [10, 9, 2],
"to": [12, 14, 4],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
}
},
{
"from": [7, 11, 11],
"to": [9, 14, 13],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#lit" }
}
}
]
} }
@@ -25,21 +25,21 @@
"to": [9, 14, 13], "to": [9, 14, 13],
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 6, 9, 11], "texture": "#unlit" }, "west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 6, 9, 11], "texture": "#unlit" } "east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
} }
}, },
{ {
"from": [7, 11, 4], "from": [7, 11, 2],
"to": [9, 14, 6], "to": [9, 14, 4],
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "north": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "south": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 6, 9, 9], "texture": "#unlit" }, "west": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 6, 9, 9], "texture": "#unlit" } "east": { "uv": [7, 9, 9, 6], "texture": "#unlit" }
} }
} }
] ]
@@ -0,0 +1,46 @@
{
"parent": "antarchy:block/bluestone_repeater",
"textures": {
"particle": "antarchy:block/bluestone/bluestone_repeater",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_repeater",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [7, 9, 11],
"to": [9, 14, 13],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
}
},
{
"from": [7, 11, 4],
"to": [9, 14, 6],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#unlit" }
}
}
]
}
@@ -0,0 +1,48 @@
{
"parent": "antarchy:block/bluestone_repeater_on",
"textures": {
"particle": "antarchy:block/bluestone/bluestone_repeater_on",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_repeater_on",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [7, 9, 11],
"to": [9, 14, 13],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
}
},
{
"from": [7, 11, 4],
"to": [9, 14, 6],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#lit" }
}
}
]
}
@@ -0,0 +1,46 @@
{
"parent": "antarchy:block/bluestone_repeater",
"textures": {
"particle": "antarchy:block/bluestone/bluestone_repeater",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_repeater",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [7, 9, 11],
"to": [9, 14, 13],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
}
},
{
"from": [7, 11, 6],
"to": [9, 14, 8],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#unlit" }
}
}
]
}
@@ -0,0 +1,48 @@
{
"parent": "antarchy:block/bluestone_repeater_on",
"textures": {
"particle": "antarchy:block/bluestone/bluestone_repeater_on",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_repeater_on",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [7, 9, 11],
"to": [9, 14, 13],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
}
},
{
"from": [7, 11, 6],
"to": [9, 14, 8],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#lit" }
}
}
]
}
@@ -0,0 +1,46 @@
{
"parent": "antarchy:block/bluestone_repeater",
"textures": {
"particle": "antarchy:block/bluestone/bluestone_repeater",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_repeater",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [7, 9, 11],
"to": [9, 14, 13],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#unlit" }
}
},
{
"from": [7, 11, 8],
"to": [9, 14, 10],
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#unlit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#unlit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#unlit" }
}
}
]
}
@@ -0,0 +1,48 @@
{
"parent": "antarchy:block/bluestone_repeater_on",
"textures": {
"particle": "antarchy:block/bluestone/bluestone_repeater_on",
"slab": "minecraft:block/smooth_stone",
"top": "antarchy:block/bluestone/bluestone_repeater_on",
"unlit": "antarchy:block/bluestone/bluestone_torch_off",
"lit": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"faces": {
"down": { "uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down" },
"up": { "uv": [0, 0, 16, 16], "texture": "#slab", "cullface": "up" },
"north": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "north" },
"south": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "south" },
"west": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "west" },
"east": { "uv": [0, 14, 16, 16], "texture": "#slab", "cullface": "east" }
}
},
{
"from": [7, 9, 11],
"to": [9, 14, 13],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
}
},
{
"from": [7, 11, 8],
"to": [9, 14, 10],
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 9, 9, 6], "texture": "#lit" }
}
}
]
}
@@ -0,0 +1,19 @@
{
"ambientocclusion": false,
"textures": {
"lock": "minecraft:block/bedrock"
},
"elements": [
{
"from": [2, 12, 6],
"to": [14, 14, 8],
"faces": {
"down": { "uv": [7, 2, 9, 14], "texture": "#lock", "rotation": 90 },
"north": { "uv": [2, 7, 14, 9], "texture": "#lock" },
"south": { "uv": [2, 7, 14, 9], "texture": "#lock" },
"west": { "uv": [6, 7, 8, 9], "texture": "#lock" },
"east": { "uv": [6, 7, 8, 9], "texture": "#lock" }
}
}
]
}
@@ -26,22 +26,22 @@
"shade": false, "shade": false,
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "north": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "south": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 6, 9, 11], "texture": "#lit" }, "west": { "uv": [7, 11, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 6, 9, 11], "texture": "#lit" } "east": { "uv": [7, 11, 9, 6], "texture": "#lit" }
} }
}, },
{ {
"from": [7, 11, 4], "from": [7, 11, 2],
"to": [9, 14, 6], "to": [9, 14, 4],
"shade": false, "shade": false,
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#lit" }, "down": { "uv": [7, 6, 9, 8], "texture": "#lit" },
"north": { "uv": [7, 6, 9, 9], "texture": "#lit" }, "north": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"south": { "uv": [7, 6, 9, 9], "texture": "#lit" }, "south": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"west": { "uv": [7, 6, 9, 9], "texture": "#lit" }, "west": { "uv": [7, 9, 9, 6], "texture": "#lit" },
"east": { "uv": [7, 6, 9, 9], "texture": "#lit" } "east": { "uv": [7, 9, 9, 6], "texture": "#lit" }
} }
} }
] ]
@@ -12,10 +12,10 @@
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#torch" }, "down": { "uv": [7, 6, 9, 8], "texture": "#torch" },
"up": { "uv": [7, 13, 9, 15], "texture": "#torch", "cullface": "up" }, "up": { "uv": [7, 13, 9, 15], "texture": "#torch", "cullface": "up" },
"north": { "uv": [7, 6, 9, 16], "texture": "#torch" }, "north": { "uv": [7, 16, 9, 6], "texture": "#torch" },
"east": { "uv": [7, 6, 9, 16], "texture": "#torch" }, "east": { "uv": [7, 16, 9, 6], "texture": "#torch" },
"south": { "uv": [7, 6, 9, 16], "texture": "#torch" }, "south": { "uv": [7, 16, 9, 6], "texture": "#torch" },
"west": { "uv": [7, 6, 9, 16], "texture": "#torch" } "west": { "uv": [7, 16, 9, 6], "texture": "#torch" }
} }
} }
] ]
@@ -12,10 +12,10 @@
"faces": { "faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#torch" }, "down": { "uv": [7, 6, 9, 8], "texture": "#torch" },
"up": { "uv": [7, 13, 9, 15], "texture": "#torch", "cullface": "up" }, "up": { "uv": [7, 13, 9, 15], "texture": "#torch", "cullface": "up" },
"north": { "uv": [7, 6, 9, 16], "texture": "#torch" }, "north": { "uv": [7, 16, 9, 6], "texture": "#torch" },
"east": { "uv": [7, 6, 9, 16], "texture": "#torch" }, "east": { "uv": [7, 16, 9, 6], "texture": "#torch" },
"south": { "uv": [7, 6, 9, 16], "texture": "#torch" }, "south": { "uv": [7, 16, 9, 6], "texture": "#torch" },
"west": { "uv": [7, 6, 9, 16], "texture": "#torch" } "west": { "uv": [7, 16, 9, 6], "texture": "#torch" }
} }
} }
] ]
@@ -0,0 +1,39 @@
{
"ambientocclusion": false,
"textures": {
"torch": "antarchy:block/bluestone/bluestone_torch",
"particle": "antarchy:block/bluestone/bluestone_torch"
},
"elements": [
{
"from": [-1, 2.5, 7],
"to": [1, 12.5, 9],
"rotation": { "origin": [0, 12.5, 8], "axis": "z", "angle": 22.5 },
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#torch" },
"up": { "uv": [7, 13, 9, 15], "texture": "#torch" }
}
},
{
"from": [-1, -3.5, 0],
"to": [1, 12.5, 16],
"rotation": { "origin": [0, 12.5, 8], "axis": "z", "angle": 22.5 },
"shade": false,
"faces": {
"west": { "uv": [0, 16, 16, 0], "texture": "#torch" },
"east": { "uv": [0, 16, 16, 0], "texture": "#torch" }
}
},
{
"from": [-8, -3.5, 7],
"to": [8, 12.5, 9],
"rotation": { "origin": [0, 12.5, 8], "axis": "z", "angle": 22.5 },
"shade": false,
"faces": {
"north": { "uv": [0, 16, 16, 0], "texture": "#torch" },
"south": { "uv": [0, 16, 16, 0], "texture": "#torch" }
}
}
]
}
@@ -0,0 +1,39 @@
{
"ambientocclusion": false,
"textures": {
"torch": "antarchy:block/bluestone/bluestone_torch_off",
"particle": "antarchy:block/bluestone/bluestone_torch_off"
},
"elements": [
{
"from": [-1, 2.5, 7],
"to": [1, 12.5, 9],
"rotation": { "origin": [0, 12.5, 8], "axis": "z", "angle": 22.5 },
"shade": false,
"faces": {
"down": { "uv": [7, 6, 9, 8], "texture": "#torch" },
"up": { "uv": [7, 13, 9, 15], "texture": "#torch" }
}
},
{
"from": [-1, -3.5, 0],
"to": [1, 12.5, 16],
"rotation": { "origin": [0, 12.5, 8], "axis": "z", "angle": 22.5 },
"shade": false,
"faces": {
"west": { "uv": [0, 16, 16, 0], "texture": "#torch" },
"east": { "uv": [0, 16, 16, 0], "texture": "#torch" }
}
},
{
"from": [-8, -3.5, 7],
"to": [8, 12.5, 9],
"rotation": { "origin": [0, 12.5, 8], "axis": "z", "angle": 22.5 },
"shade": false,
"faces": {
"north": { "uv": [0, 16, 16, 0], "texture": "#torch" },
"south": { "uv": [0, 16, 16, 0], "texture": "#torch" }
}
}
]
}
@@ -1,7 +1,7 @@
{ {
"parent": "minecraft:block/redstone_dust_dot", "parent": "minecraft:block/redstone_dust_dot",
"textures": { "textures": {
"cross": "antarchy:block/bluestone/bluestone_dust_dot", "line": "antarchy:block/bluestone/bluestone_dust_dot",
"overlay": "antarchy:block/bluestone/bluestone_dust_overlay" "overlay": "antarchy:block/bluestone/bluestone_dust_overlay"
} }
} }
@@ -0,0 +1,8 @@
{
"parent": "minecraft:block/redstone_dust_up",
"textures": {
"line": "antarchy:block/bluestone/bluestone_dust_line0",
"overlay": "antarchy:block/bluestone/bluestone_dust_overlay",
"particle": "antarchy:block/bluestone/bluestone_dust_dot"
}
}
@@ -1,7 +1,18 @@
{ {
"parent": "minecraft:block/redstone_dust_line0", "ambientocclusion": false,
"textures": { "textures": {
"line": "antarchy:block/bluestone/bluestone_dust_line0", "particle": "antarchy:block/bluestone/bluestone_dust_line0",
"overlay": "antarchy:block/bluestone/bluestone_dust_overlay" "line": "antarchy:block/bluestone/bluestone_dust_line0"
},
"elements": [
{
"from": [0, 0, 7.0],
"to": [16, 0, 9.0],
"shade": false,
"faces": {
"up": { "uv": [0, 0, 16, 2], "texture": "#line", "tintindex": 0 },
"down": { "uv": [0, 0, 16, 2], "texture": "#line", "tintindex": 0 }
} }
} }
]
}
Loaded 100 of 180 files, more files were not shown because too many files have changed in this diff. Show more