starting work on modeling. oh god. why.

This commit is contained in:
gamma-delta 2022-06-16 22:09:14 -05:00
parent 46cc0b55cc
commit a03f80de2e
25 changed files with 412 additions and 951 deletions

View file

@ -1,37 +1,151 @@
package at.petrak.hexcasting.api.block.circle;
import at.petrak.hexcasting.api.circles.Margin;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
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.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
/**
* Block holder of a {@link BlockEntitySidedCircleWidget}.
*/
public class BlockSidedCircleWidget extends Block {
abstract public class BlockSidedCircleWidget extends Block implements EntityBlock {
public static final double THICKNESS = 8;
public static final VoxelShape AABB_XP = Block.box(0, 0, 0, THICKNESS, 16, 16);
public static final VoxelShape AABB_XN = Block.box(16 - THICKNESS, 0, 0, 16, 16, 16);
public static final VoxelShape AABB_YP = Block.box(0, 16 - THICKNESS, 0, 16, 16, 16);
public static final VoxelShape AABB_YN = Block.box(0, 0, 0, 16, THICKNESS, 16);
public static final VoxelShape AABB_ZP = Block.box(0, 0, 0, 16, 16, THICKNESS);
public static final VoxelShape AABB_ZN = Block.box(0, 0, 16 - THICKNESS, 16, 16, 16);
public static final VoxelShape AABB_XP = Block.box(16 - THICKNESS, 0, 0, 16, 16, 16);
public static final VoxelShape AABB_XN = Block.box(0, 0, 0, THICKNESS, 16, 16);
public static final VoxelShape AABB_YP = Block.box(0, 0, 0, 16, THICKNESS, 16);
public static final VoxelShape AABB_YN = Block.box(0, 16 - THICKNESS, 0, 16, 16, 16);
public static final VoxelShape AABB_ZP = Block.box(0, 0, 16 - THICKNESS, 16, 16, 16);
public static final VoxelShape AABB_ZN = Block.box(0, 0, 0, 16, 16, THICKNESS);
/**
* If this has been activated yet by the circle.
*/
public static final BooleanProperty ENERGIZED = BooleanProperty.create("energized");
/**
* The normal vector of this block
*/
public static final DirectionProperty FACING = BlockStateProperties.FACING;
/**
* Which margin this block considers to be its "top."
* Which margin this block considers to be its "top." AKA, its local facing dir.
*/
public static final EnumProperty<Margin> TOP_MARGIN = EnumProperty.create("top_margin", Margin.class);
// storing these 4 properties raises the property count to 384, but minecraft noteblocks have like 768
// I'll be fiiiiiiiiiiiiine
public static final BooleanProperty TOP_CONNECTS = BooleanProperty.create("top_connects");
public static final BooleanProperty RIGHT_CONNECTS = BooleanProperty.create("right_connects");
public static final BooleanProperty BOTTOM_CONNECTS = BooleanProperty.create("bottom_connects");
public static final BooleanProperty LEFT_CONNECTS = BooleanProperty.create("left_connects");
public BlockSidedCircleWidget(Properties properties) {
super(properties);
var statedef = this.getStateDefinition().any()
.setValue(ENERGIZED, false)
.setValue(FACING, Direction.NORTH)
.setValue(TOP_MARGIN, Margin.TOP);
for (var margin : Margin.values()) {
statedef = statedef.setValue(getConnectorProp(margin), false);
}
this.registerDefaultState(statedef);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(ENERGIZED, FACING, TOP_MARGIN);
for (var margin : Margin.values()) {
builder.add(getConnectorProp(margin));
}
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return switch (state.getValue(FACING)) {
case DOWN -> AABB_YN;
case UP -> AABB_YP;
case NORTH -> AABB_ZN;
case SOUTH -> AABB_ZP;
case WEST -> AABB_XN;
case EAST -> AABB_XP;
};
}
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
var normal = ctx.getClickedFace();
if (ctx.isSecondaryUseActive()) {
normal = normal.getOpposite();
}
var margin = getHoveredMargin(ctx.getClickLocation(), normal);
return this.defaultBlockState()
.setValue(FACING, normal)
.setValue(TOP_MARGIN, margin);
}
/**
* Calculate the little triangle overlay thing IE does.
*/
public static Margin getHoveredMargin(Vec3 clickPos, Direction normal) {
// uv cause textures
double u, v;
switch (normal.getAxis()) {
case X -> {
u = Mth.positiveModulo(clickPos.z * -1 * normal.getAxisDirection().getStep(), 1);
v = Mth.positiveModulo(clickPos.y, 1);
}
case Y -> {
// North is "up", so +v here ...
// and u is a quarter-turn to the right, so east.
u = Mth.positiveModulo(clickPos.x * normal.getAxisDirection().getStep(), 1);
v = Mth.positiveModulo(clickPos.z * -1 * normal.getAxisDirection().getStep(), 1);
}
case Z -> {
u = Mth.positiveModulo(clickPos.x * normal.getAxisDirection().getStep(), 1);
v = Mth.positiveModulo(clickPos.y, 1);
}
default -> throw new IllegalStateException();
}
u -= 0.5;
v -= 0.5;
// i have done some futzing around with desmos
// also i know this is shoddy code, but i've never found a good way to do this matrix of boolean thing,
// especially when I cant `match` on a tuple of booleans. so i'll just comment.
// this is true when the point is in an "hourglass", within two triangles radiating up and down...
var flag1 = Math.abs(u) < Math.abs(v) ? 1 : 0;
// ... and this is true in the upper-left diagonal half of the coordinate plane
var flag2 = u < v ? 1 : 0;
var id = (flag1 << 1) | flag2;
return switch (id) {
case 0b00 -> Margin.RIGHT;
case 0b01 -> Margin.LEFT;
case 0b10 -> Margin.BOTTOM;
case 0b11 -> Margin.TOP;
default -> throw new IllegalStateException();
};
}
public static BooleanProperty getConnectorProp(Margin margin) {
return switch (margin) {
case TOP -> TOP_CONNECTS;
case LEFT -> LEFT_CONNECTS;
case BOTTOM -> BOTTOM_CONNECTS;
case RIGHT -> RIGHT_CONNECTS;
};
}
}

View file

@ -1,82 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.api.block.circle.BlockEntityCircleWidget;
import at.petrak.hexcasting.api.spell.math.HexPattern;
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.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.material.PushReaction;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
// As it turns out, not actually an impetus
public class BlockEmptyImpetus extends BlockEntityCircleWidget {
public static final DirectionProperty FACING = BlockStateProperties.FACING;
public BlockEmptyImpetus(Properties p_49795_) {
super(p_49795_);
this.registerDefaultState(this.stateDefinition.any()
.setValue(ENERGIZED, false).setValue(FACING, Direction.NORTH));
}
@Override
public boolean canEnterFromDirection(Direction enterDir, Direction normalDir, BlockPos pos, BlockState bs,
Level world) {
return enterDir != bs.getValue(FACING);
}
@Override
public EnumSet<Direction> exitDirections(BlockPos pos, BlockState bs, Level world) {
return EnumSet.of(bs.getValue(FACING));
}
@Override
public @Nullable HexPattern getPattern(BlockPos pos, BlockState bs, Level world) {
return null;
}
@Override
public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) {
return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft);
}
@Override
public float particleHeight(BlockPos pos, BlockState bs, Level world) {
return 0.5f;
}
@Override
public PushReaction getPistonPushReaction(BlockState pState) {
return PushReaction.BLOCK;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
return this.defaultBlockState().setValue(FACING, pContext.getNearestLookingDirection());
}
@Override
public BlockState rotate(BlockState pState, Rotation pRot) {
return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING)));
}
@Override
public BlockState mirror(BlockState pState, Mirror pMirror) {
return pState.rotate(pMirror.getRotation(pState.getValue(FACING)));
}
}

View file

@ -1,45 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public class BlockEntitySlate extends HexBlockEntity {
public static final String TAG_PATTERN = "pattern";
@Nullable
public HexPattern pattern;
public BlockEntitySlate(BlockPos pos, BlockState state) {
super(HexBlockEntities.SLATE_TILE, pos, state);
}
@Override
protected void saveModData(CompoundTag tag) {
if (this.pattern != null) {
tag.put(TAG_PATTERN, this.pattern.serializeToNBT());
} else {
tag.put(TAG_PATTERN, new CompoundTag());
}
}
@Override
protected void loadModData(CompoundTag tag) {
if (tag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) {
CompoundTag patternTag = tag.getCompound(TAG_PATTERN);
if (HexPattern.isPattern(patternTag)) {
this.pattern = HexPattern.fromNBT(patternTag);
} else {
this.pattern = null;
}
} else {
this.pattern = null;
}
}
}

View file

@ -1,217 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.block.circle.BlockEntityCircleWidget;
import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexItems;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.*;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import java.util.EnumSet;
// When on the floor or ceiling FACING is the direction the *bottom* of the pattern points
// (or which way is "down").
// When on the wall FACING is the direction of the *front* of the block
public class BlockSlate extends BlockEntityCircleWidget implements EntityBlock, SimpleWaterloggedBlock {
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final EnumProperty<AttachFace> ATTACH_FACE = BlockStateProperties.ATTACH_FACE;
public static final double THICKNESS = 1;
public static final VoxelShape AABB_FLOOR = Block.box(0, 0, 0, 16, THICKNESS, 16);
public static final VoxelShape AABB_CEILING = Block.box(0, 16 - THICKNESS, 0, 16, 16, 16);
public static final VoxelShape AABB_EAST_WALL = Block.box(0, 0, 0, THICKNESS, 16, 16);
public static final VoxelShape AABB_WEST_WALL = Block.box(16 - THICKNESS, 0, 0, 16, 16, 16);
public static final VoxelShape AABB_SOUTH_WALL = Block.box(0, 0, 0, 16, 16, THICKNESS);
public static final VoxelShape AABB_NORTH_WALL = Block.box(0, 0, 16 - THICKNESS, 16, 16, 16);
public BlockSlate(Properties p_53182_) {
super(p_53182_);
this.registerDefaultState(
this.stateDefinition.any()
.setValue(ENERGIZED, false)
.setValue(FACING, Direction.NORTH)
.setValue(WATERLOGGED, false));
}
@Override
public boolean propagatesSkylightDown(BlockState state, @Nonnull BlockGetter reader, @Nonnull BlockPos pos) {
return !state.getValue(WATERLOGGED);
}
@Nonnull
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}
@Override
public boolean canEnterFromDirection(Direction enterDir, Direction normalDir, BlockPos pos, BlockState bs,
Level world) {
var thisNormal = this.normalDir(pos, bs, world);
return enterDir != thisNormal && normalDir == thisNormal;
}
@Override
public EnumSet<Direction> exitDirections(BlockPos pos, BlockState bs, Level world) {
var allDirs = EnumSet.allOf(Direction.class);
var normal = this.normalDir(pos, bs, world);
allDirs.remove(normal);
allDirs.remove(normal.getOpposite());
return allDirs;
}
@Override
public @Nullable
HexPattern getPattern(BlockPos pos, BlockState bs, Level world) {
if (world.getBlockEntity(pos) instanceof BlockEntitySlate tile) {
return tile.pattern;
} else {
return null;
}
}
@SoftImplement("forge")
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos,
Player player) {
BlockEntity be = level.getBlockEntity(pos);
if (be instanceof BlockEntitySlate slate) {
ItemStack stack = new ItemStack(HexItems.SLATE);
if (slate.pattern != null) {
HexItems.SLATE.writeDatum(stack, new PatternIota(slate.pattern));
}
return stack;
}
return new ItemStack(this);
}
@Override
public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) {
return switch (bs.getValue(ATTACH_FACE)) {
case FLOOR -> Direction.UP;
case CEILING -> Direction.DOWN;
case WALL -> bs.getValue(FACING);
};
}
@Override
public float particleHeight(BlockPos pos, BlockState bs, Level world) {
return 0.5f - 15f / 16f;
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
return new BlockEntitySlate(pPos, pState);
}
@Override
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
return switch (pState.getValue(ATTACH_FACE)) {
case FLOOR -> AABB_FLOOR;
case CEILING -> AABB_CEILING;
case WALL -> switch (pState.getValue(FACING)) {
case NORTH -> AABB_NORTH_WALL;
case EAST -> AABB_EAST_WALL;
case SOUTH -> AABB_SOUTH_WALL;
// NORTH; up and down don't happen (but we need branches for them)
default -> AABB_WEST_WALL;
};
};
}
@Override
public PushReaction getPistonPushReaction(BlockState pState) {
return PushReaction.DESTROY;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(FACING, ATTACH_FACE, WATERLOGGED);
}
@Override
@Nullable
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos());
for (Direction direction : pContext.getNearestLookingDirections()) {
BlockState blockstate;
if (direction.getAxis() == Direction.Axis.Y) {
blockstate = this.defaultBlockState()
.setValue(ATTACH_FACE, direction == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR)
.setValue(FACING, pContext.getHorizontalDirection().getOpposite());
} else {
blockstate = this.defaultBlockState()
.setValue(ATTACH_FACE, AttachFace.WALL)
.setValue(FACING, direction.getOpposite());
}
blockstate = blockstate.setValue(WATERLOGGED,
fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8);
if (blockstate.canSurvive(pContext.getLevel(), pContext.getClickedPos())) {
return blockstate;
}
}
return null;
}
// i do as the FaceAttachedHorizontalDirectionBlock.java guides
@Override
public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) {
return canAttach(pLevel, pPos, getConnectedDirection(pState).getOpposite());
}
@Override
public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel,
BlockPos pCurrentPos, BlockPos pFacingPos) {
if (pState.getValue(WATERLOGGED)) {
pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel));
}
return getConnectedDirection(pState).getOpposite() == pFacing
&& !pState.canSurvive(pLevel, pCurrentPos) ?
pState.getFluidState().createLegacyBlock()
: super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos);
}
public static boolean canAttach(LevelReader pReader, BlockPos pPos, Direction pDirection) {
BlockPos blockpos = pPos.relative(pDirection);
return pReader.getBlockState(blockpos).isFaceSturdy(pReader, blockpos, pDirection.getOpposite());
}
protected static Direction getConnectedDirection(BlockState pState) {
return switch (pState.getValue(ATTACH_FACE)) {
case CEILING -> Direction.DOWN;
case FLOOR -> Direction.UP;
default -> pState.getValue(FACING);
};
}
}

View file

@ -1,79 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles.directrix;
import at.petrak.hexcasting.api.block.circle.BlockEntityCircleWidget;
import at.petrak.hexcasting.api.spell.math.HexPattern;
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.block.Block;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.PushReaction;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
public class BlockEmptyDirectrix extends BlockEntityCircleWidget {
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.AXIS;
public BlockEmptyDirectrix(Properties p_49795_) {
super(p_49795_);
this.registerDefaultState(this.stateDefinition.any()
.setValue(ENERGIZED, false)
.setValue(AXIS, Direction.Axis.X));
}
@Override
public boolean canEnterFromDirection(Direction enterDir, Direction normalDir, BlockPos pos, BlockState bs,
Level world) {
return true;
}
@Override
public EnumSet<Direction> exitDirections(BlockPos pos, BlockState bs, Level world) {
var sign = world.random.nextBoolean() ? Direction.AxisDirection.POSITIVE : Direction.AxisDirection.NEGATIVE;
return EnumSet.of(Direction.fromAxisAndDirection(bs.getValue(AXIS), sign));
}
@Override
public @Nullable HexPattern getPattern(BlockPos pos, BlockState bs, Level world) {
return null;
}
@Override
public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) {
return Direction.UP;
}
@Override
public float particleHeight(BlockPos pos, BlockState bs, Level world) {
return 0.5f;
}
@Override
public PushReaction getPistonPushReaction(BlockState pState) {
return PushReaction.BLOCK;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(AXIS);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
return this.defaultBlockState().setValue(AXIS, pContext.getNearestLookingDirection().getAxis());
}
@Override
public BlockState rotate(BlockState pState, Rotation pRot) {
return pState.setValue(AXIS,
pRot.rotate(Direction.get(Direction.AxisDirection.POSITIVE, pState.getValue(AXIS))).getAxis());
}
}

View file

@ -1,127 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles.directrix;
import at.petrak.hexcasting.api.block.circle.BlockEntityCircleWidget;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.Random;
public class BlockRedstoneDirectrix extends BlockEntityCircleWidget {
public static final DirectionProperty FACING = BlockStateProperties.FACING;
public static final BooleanProperty REDSTONE_POWERED = BlockStateProperties.POWERED;
public BlockRedstoneDirectrix(Properties p_49795_) {
super(p_49795_);
this.registerDefaultState(this.stateDefinition.any()
.setValue(REDSTONE_POWERED, false)
.setValue(ENERGIZED, false)
.setValue(FACING, Direction.NORTH));
}
@Override
public boolean canEnterFromDirection(Direction enterDir, Direction normalDir, BlockPos pos, BlockState bs,
Level world) {
return enterDir != getRealFacing(bs);
}
@Override
public EnumSet<Direction> exitDirections(BlockPos pos, BlockState bs, Level world) {
return EnumSet.of(getRealFacing(bs));
}
@Override
public @Nullable HexPattern getPattern(BlockPos pos, BlockState bs, Level world) {
return null;
}
@Override
public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) {
return normalDirOfOther(pos.relative(getRealFacing(bs)), world, recursionLeft);
}
@Override
public float particleHeight(BlockPos pos, BlockState bs, Level world) {
return 0.5f;
}
protected Direction getRealFacing(BlockState bs) {
var facing = bs.getValue(FACING);
if (bs.getValue(REDSTONE_POWERED)) {
return facing.getOpposite();
} else {
return facing;
}
}
@Override
public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos,
boolean pIsMoving) {
super.neighborChanged(pState, pLevel, pPos, pBlock, pFromPos, pIsMoving);
if (!pLevel.isClientSide) {
boolean currentlyPowered = pState.getValue(REDSTONE_POWERED);
if (currentlyPowered != pLevel.hasNeighborSignal(pPos)) {
pLevel.setBlock(pPos, pState.setValue(REDSTONE_POWERED, !currentlyPowered), 2);
}
}
}
@Override
public void animateTick(BlockState bs, Level pLevel, BlockPos pos, Random rand) {
if (bs.getValue(REDSTONE_POWERED)) {
for (int i = 0; i < 2; i++) {
var step = bs.getValue(FACING).getOpposite().step();
var center = Vec3.atCenterOf(pos).add(step.x() * 0.5, step.y() * 0.5, step.z() * 0.5);
double x = center.x + (rand.nextDouble() - 0.5) * 0.5D;
double y = center.y + (rand.nextDouble() - 0.5) * 0.5D;
double z = center.z + (rand.nextDouble() - 0.5) * 0.5D;
pLevel.addParticle(DustParticleOptions.REDSTONE, x, y, z,
step.x() * 0.1, step.y() * 0.1, step.z() * 0.1);
}
}
}
@Override
public PushReaction getPistonPushReaction(BlockState pState) {
return PushReaction.BLOCK;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(REDSTONE_POWERED, FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
return this.defaultBlockState().setValue(FACING, pContext.getNearestLookingDirection());
}
@Override
public BlockState rotate(BlockState pState, Rotation pRot) {
return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING)));
}
@Override
public BlockState mirror(BlockState pState, Mirror pMirror) {
return pState.rotate(pMirror.getRotation(pState.getValue(FACING)));
}
}

View file

@ -1,45 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles.impetuses;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityLookingImpetus;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public class BlockLookingImpetus extends BlockAbstractImpetus {
public BlockLookingImpetus(Properties p_49795_) {
super(p_49795_);
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
return new BlockEntityLookingImpetus(pPos, pState);
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState,
BlockEntityType<T> type) {
if (!pLevel.isClientSide) {
return createTickerHelper(type, HexBlockEntities.IMPETUS_LOOK_TILE,
BlockEntityLookingImpetus::serverTick);
} else {
return null;
}
}
// uegh
@Nullable
@SuppressWarnings("unchecked")
protected static <E extends BlockEntity, A extends BlockEntity> BlockEntityTicker<A> createTickerHelper(
BlockEntityType<A> type, BlockEntityType<E> targetType, BlockEntityTicker<? super E> ticker) {
return targetType == type ? (BlockEntityTicker<A>) ticker : null;
}
}

View file

@ -1,41 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles.impetuses;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityRightClickImpetus;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable;
public class BlockRightClickImpetus extends BlockAbstractImpetus {
public BlockRightClickImpetus(Properties p_49795_) {
super(p_49795_);
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
return new BlockEntityRightClickImpetus(pPos, pState);
}
@Override
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
BlockHitResult pHit) {
if (!pPlayer.isShiftKeyDown()) {
var tile = pLevel.getBlockEntity(pPos);
if (tile instanceof BlockEntityRightClickImpetus impetus) {
if (pPlayer instanceof ServerPlayer serverPlayer) {
impetus.activateSpellCircle(serverPlayer);
}
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}
}

View file

@ -1,104 +0,0 @@
package at.petrak.hexcasting.common.blocks.circles.impetuses;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.spell.iota.EntityIota;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityStoredPlayerImpetus;
import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
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.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable;
import java.util.Random;
public class BlockStoredPlayerImpetus extends BlockAbstractImpetus {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
public BlockStoredPlayerImpetus(Properties p_49795_) {
super(p_49795_);
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
return new BlockEntityStoredPlayerImpetus(pPos, pState);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(POWERED);
}
@Override
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
BlockHitResult pHit) {
if (pLevel.getBlockEntity(pPos) instanceof BlockEntityStoredPlayerImpetus tile) {
var usedStack = pPlayer.getItemInHand(pHand);
var datumContainer = IXplatAbstractions.INSTANCE.findDataHolder(usedStack);
if (datumContainer != null) {
if (pLevel instanceof ServerLevel level) {
var stored = datumContainer.readIota(level);
if (stored instanceof EntityIota eieio) {
var entity = eieio.getEntity();
if (entity instanceof Player player) {
// phew, we got something
tile.setPlayer(player.getGameProfile(), entity.getUUID());
level.sendBlockUpdated(pPos, pState, pState, Block.UPDATE_CLIENTS);
pLevel.playSound(pPlayer, pPos, HexSounds.IMPETUS_STOREDPLAYER_DING,
SoundSource.BLOCKS, 1f, 1f);
}
}
}
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}
@Override
public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, Random pRandom) {
super.tick(pState, pLevel, pPos, pRandom);
if (pLevel.getBlockEntity(pPos) instanceof BlockEntityStoredPlayerImpetus tile) {
tile.updatePlayerProfile();
}
}
@Override
public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos,
boolean pIsMoving) {
super.neighborChanged(pState, pLevel, pPos, pBlock, pFromPos, pIsMoving);
if (!pLevel.isClientSide()) {
boolean prevPowered = pState.getValue(POWERED);
boolean isPowered = pLevel.hasNeighborSignal(pPos);
if (prevPowered != isPowered) {
pLevel.setBlockAndUpdate(pPos, pState.setValue(POWERED, isPowered));
if (isPowered && pLevel.getBlockEntity(pPos) instanceof BlockEntityStoredPlayerImpetus tile) {
var player = tile.getStoredPlayer();
if (player instanceof ServerPlayer splayer) {
// phew
tile.activateSpellCircle(splayer);
}
}
}
}
}
}

View file

@ -1,19 +1,11 @@
package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.common.blocks.BlockConjured;
import at.petrak.hexcasting.common.blocks.BlockConjuredLight;
import at.petrak.hexcasting.common.blocks.BlockFlammable;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicLigature;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord;
import at.petrak.hexcasting.common.blocks.circles.BlockEmptyImpetus;
import at.petrak.hexcasting.common.blocks.circles.BlockSlate;
import at.petrak.hexcasting.common.blocks.circles.directrix.BlockEmptyDirectrix;
import at.petrak.hexcasting.common.blocks.circles.directrix.BlockRedstoneDirectrix;
import at.petrak.hexcasting.common.blocks.circles.impetuses.BlockLookingImpetus;
import at.petrak.hexcasting.common.blocks.circles.impetuses.BlockRightClickImpetus;
import at.petrak.hexcasting.common.blocks.circles.impetuses.BlockStoredPlayerImpetus;
import at.petrak.hexcasting.common.blocks.decoration.*;
import com.mojang.datafixers.util.Pair;
import net.minecraft.resources.ResourceLocation;
@ -118,6 +110,7 @@ public class HexBlocks {
.isViewBlocking(HexBlocks::never)),
new Item.Properties());
/*
// "no" item because we add it manually
public static final BlockSlate SLATE = blockNoItem("slate", new BlockSlate(slateish()));
@ -137,6 +130,7 @@ public class HexBlocks {
new BlockEmptyDirectrix(slateish()));
public static final BlockRedstoneDirectrix DIRECTRIX_REDSTONE = blockItem("directrix_redstone",
new BlockRedstoneDirectrix(slateish()));
*/
public static final BlockAkashicRecord AKASHIC_RECORD = blockItem("akashic_record",
new BlockAkashicRecord(akashicWoodyHard().lightLevel(bs -> 15)));

View file

@ -0,0 +1,55 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"particle": "hexcasting:block/circle/common",
"common": "hexcasting:block/circle/common",
"core": "hexcasting:block/circle/impetus"
},
"elements": [
{
"name": "body",
"from": [2, 0, 2],
"to": [14, 8, 14],
"faces": {
"north": {"uv": [1, 4, 7, 8], "texture": "#common"},
"east": {"uv": [1, 4, 7, 8], "texture": "#common"},
"south": {"uv": [1, 4, 7, 8], "texture": "#common"},
"west": {"uv": [1, 4, 7, 8], "texture": "#common"},
"up": {"uv": [2, 2, 14, 14], "texture": "#core"},
"down": {"uv": [9, 1, 15, 7], "rotation": 270, "texture": "#common"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -0,0 +1,55 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"particle": "hexcasting:block/circle/common",
"common": "hexcasting:block/circle/common",
"core": "hexcasting:block/circle/impetus"
},
"elements": [
{
"name": "east",
"from": [14, 0, 4],
"to": [16, 4, 12],
"faces": {
"north": {"uv": [0, 12, 2, 16], "texture": "#core"},
"east": {"uv": [0, 0, 4, 2], "texture": "#common"},
"south": {"uv": [0, 12, 2, 16], "texture": "#core"},
"west": {"uv": [0, 0, 4.5, 1], "texture": "#missing"},
"up": {"uv": [14, 4, 16, 12], "texture": "#core"},
"down": {"uv": [14, 4, 16, 12], "rotation": 180, "texture": "#core"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -0,0 +1,55 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"particle": "hexcasting:block/circle/common",
"common": "hexcasting:block/circle/common",
"core": "hexcasting:block/circle/impetus"
},
"elements": [
{
"name": "north",
"from": [4, 0, 0],
"to": [12, 4, 2],
"faces": {
"north": {"uv": [0, 0, 4, 2], "texture": "#common"},
"east": {"uv": [0, 0, 2, 4], "texture": "#core"},
"south": {"uv": [0, 0, 4, 1], "texture": "#missing"},
"west": {"uv": [0, 0, 2, 4], "texture": "#core"},
"up": {"uv": [4, 0, 12, 2], "texture": "#core"},
"down": {"uv": [4, 0, 12, 2], "texture": "#core"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -0,0 +1,55 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"particle": "hexcasting:block/circle/common",
"common": "hexcasting:block/circle/common",
"core": "hexcasting:block/circle/impetus"
},
"elements": [
{
"name": "south",
"from": [4, 0, 14],
"to": [12, 4, 16],
"faces": {
"north": {"uv": [0, 0, 4, 1], "texture": "#missing"},
"east": {"uv": [14, 12, 16, 16], "texture": "#core"},
"south": {"uv": [0, 0, 4, 2], "texture": "#common"},
"west": {"uv": [14, 12, 16, 16], "texture": "#core"},
"up": {"uv": [4, 14, 12, 16], "texture": "#core"},
"down": {"uv": [4, 14, 12, 16], "texture": "#core"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -0,0 +1,55 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"particle": "hexcasting:block/circle/common",
"common": "hexcasting:block/circle/common",
"core": "hexcasting:block/circle/impetus"
},
"elements": [
{
"name": "west",
"from": [0, 0, 4],
"to": [2, 4, 12],
"faces": {
"north": {"uv": [14, 0, 16, 4], "texture": "#core"},
"east": {"uv": [0, 0, 4.5, 1], "texture": "#missing"},
"south": {"uv": [14, 0, 16, 4], "texture": "#core"},
"west": {"uv": [0, 0, 4, 2], "texture": "#common"},
"up": {"uv": [0, 4, 2, 12], "texture": "#core"},
"down": {"uv": [0, 4, 2, 12], "rotation": 180, "texture": "#core"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

View file

@ -1,17 +1,13 @@
package at.petrak.hexcasting.forge.datagen.xplat;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.block.circle.BlockEntityCircleWidget;
import at.petrak.hexcasting.api.block.circle.BlockSidedCircleWidget;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.circles.BlockSlate;
import at.petrak.hexcasting.common.blocks.circles.directrix.BlockRedstoneDirectrix;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.paucal.api.forge.datagen.PaucalBlockStateAndModelProvider;
import net.minecraft.core.Direction;
import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraftforge.client.model.generators.BlockModelBuilder;
import net.minecraftforge.client.model.generators.ConfiguredModel;
import net.minecraftforge.common.data.ExistingFileHelper;
@ -26,101 +22,6 @@ public class HexBlockStatesAndModels extends PaucalBlockStateAndModelProvider {
@Override
protected void registerStatesAndModels() {
var slateModel = models().getExistingFile(modLoc("slate"));
getVariantBuilder(HexBlocks.SLATE).forAllStatesExcept(bs -> {
int rotationX = 0;
int rotationY = 0;
switch (bs.getValue(BlockSlate.ATTACH_FACE)) {
case CEILING -> rotationX = 180;
case WALL -> {
rotationX = 90;
rotationY = bs.getValue(BlockSlate.FACING).getOpposite().get2DDataValue() * 90;
}
}
return ConfiguredModel.builder()
.modelFile(slateModel)
.rotationX(rotationX)
.rotationY(rotationY)
.uvLock(true)
.build();
}, BlockSlate.WATERLOGGED);
impetus(HexBlocks.IMPETUS_RIGHTCLICK, "impetus_rightclick", "rightclick");
impetus(HexBlocks.IMPETUS_LOOK, "impetus_look", "look");
impetus(HexBlocks.IMPETUS_STOREDPLAYER, "impetus_storedplayer", "storedplayer");
arrowCircleBlock(HexBlocks.EMPTY_IMPETUS, "empty_impetus", modLoc("block/slate"),
"impetus/front_empty",
"impetus/back_empty",
"impetus/up_empty",
"impetus/down_empty",
"impetus/left_empty",
"impetus/right_empty"
);
// auugh
getVariantBuilder(HexBlocks.DIRECTRIX_REDSTONE).forAllStates(bs -> {
var isLit = bs.getValue(BlockEntityCircleWidget.ENERGIZED);
var litness = isLit ? "lit" : "dim";
var isPowered = bs.getValue(BlockRedstoneDirectrix.REDSTONE_POWERED);
var poweredness = isPowered ? "powered" : "unpowered";
var dir = bs.getValue(BlockStateProperties.FACING);
var up = modLoc("block/directrix/redstone/up_" + poweredness + "_" + litness);
var left = modLoc("block/directrix/redstone/left_" + poweredness + "_" + litness);
var right = modLoc("block/directrix/redstone/right_" + poweredness + "_" + litness);
var down = modLoc("block/directrix/redstone/down_" + poweredness + "_" + litness);
var front = modLoc("block/directrix/redstone/front_" + litness);
var back = modLoc("block/directrix/redstone/back_" + poweredness);
var routing = routeReslocsForArrowBlock(dir, front, back, up, down, left, right);
var modelName = "redstone_directrix_" + poweredness + "_" + litness + "_" + dir.getName();
var model = models().cube(modelName, routing[0], routing[1], routing[2], routing[3], routing[4], routing[5])
.texture("particle", modLoc("block/slate"));
if (!isLit && !isPowered && dir == Direction.NORTH) {
simpleBlockItem(HexBlocks.DIRECTRIX_REDSTONE, model);
}
return ConfiguredModel.builder()
.modelFile(model)
.build();
});
getVariantBuilder(HexBlocks.EMPTY_DIRECTRIX).forAllStates(bs -> {
var isLit = bs.getValue(BlockEntityCircleWidget.ENERGIZED);
var litness = isLit ? "lit" : "dim";
var axis = bs.getValue(BlockStateProperties.AXIS);
var horiz = modLoc("block/directrix/empty/horiz_" + litness);
var vert = modLoc("block/directrix/empty/vert_" + litness);
var end = modLoc("block/directrix/empty/end_" + litness);
ResourceLocation x = null, y = null, z = null;
switch (axis) {
case X -> {
x = end;
y = horiz;
z = horiz;
}
case Y -> {
x = vert;
y = end;
z = vert;
}
case Z -> {
x = horiz;
y = vert;
z = end;
}
}
var modelName = "empty_directrix_" + litness + "_" + axis.getName();
var model = models().cube(modelName, y, y, z, z, x, x)
.texture("particle", modLoc("block/slate"));
if (!isLit && axis == Direction.Axis.Z) {
simpleBlockItem(HexBlocks.EMPTY_DIRECTRIX, model);
}
return ConfiguredModel.builder()
.modelFile(model)
.build();
});
var akashicRecordModel = models().getExistingFile(modLoc("block/akashic_record"));
simpleBlock(HexBlocks.AKASHIC_RECORD, akashicRecordModel);
@ -236,99 +137,16 @@ public class HexBlockStatesAndModels extends PaucalBlockStateAndModelProvider {
simpleBlock(HexBlocks.CONJURED_LIGHT, conjuredModel);
}
private void impetus(Block block, String name, String stub) {
arrowCircleBlock(block, name, modLoc("block/slate"),
"impetus/" + stub,
"impetus/back",
"impetus/up",
"impetus/down",
"impetus/left",
"impetus/right"
);
private void sidedCircleWidget(BlockSidedCircleWidget widget, String commonName, String coreName) {
// We do really need to do this with a multipart builder. Unfortunately we cannot combine this with a variant builder,
// so there's gonna be a *lot* of model files.
// Each block needs a body + 4 connector models, for unenergized and energized versions, for non-margin
// and margin versions. ("Margin" = the overlay model we stick on top, so some of the model rotates and some doesn't.)
//
// To avoid the generated folder becoming incredibly thicc and to save resource pack makers we put everything in a folder.
//
// Files are named {blockpath}/{part}['_' margin]['_' energized].
// So, `toolsmith_impetus/body_energized` for the large chunk in the middle when active,
// `farmer_locus/north_margin` for the north connector when rendering the overlay, etc.
}
private void arrowCircleBlock(Block block, String name, ResourceLocation particle, String frontStub,
String backStub, String upStub, String downStub, String leftStub, String rightStub) {
getVariantBuilder(block).forAllStates(bs -> {
var isLit = bs.getValue(BlockEntityCircleWidget.ENERGIZED);
var litness = isLit ? "lit" : "dim";
var dir = bs.getValue(BlockStateProperties.FACING);
var up = modLoc("block/" + upStub + "_" + litness);
var front = modLoc("block/" + frontStub + "_" + litness);
var back = modLoc("block/" + backStub + "_" + litness);
var left = modLoc("block/" + leftStub + "_" + litness);
var right = modLoc("block/" + rightStub + "_" + litness);
var down = modLoc("block/" + downStub + "_" + litness);
var routing = routeReslocsForArrowBlock(dir, front, back, up, down, left, right);
var modelName = name + "_" + litness + "_" + dir.getName();
var model = models().cube(modelName, routing[0], routing[1], routing[2], routing[3], routing[4], routing[5])
.texture("particle", particle);
// Ordinarily i would use north, because north is the lower-right direction in the inv
// and that's where other blocks face.
// But impetuses are only distinguished by their front faces and I don't want it covered
// by the number.
if (!isLit && dir == Direction.EAST) {
simpleBlockItem(block, model);
}
return ConfiguredModel.builder()
.modelFile(model)
.build();
});
}
private static ResourceLocation[] routeReslocsForArrowBlock(Direction dir, ResourceLocation front,
ResourceLocation back,
ResourceLocation up, ResourceLocation down,
ResourceLocation left, ResourceLocation right) {
ResourceLocation bottom = null, top = null, north = null, south = null, east = null, west = null;
switch (dir) {
case UP -> {
top = front;
bottom = back;
north = east = south = west = up;
}
case DOWN -> {
bottom = front;
top = back;
north = east = south = west = down;
}
case NORTH -> {
north = front;
south = back;
west = left;
east = right;
top = up;
bottom = down;
}
case SOUTH -> {
south = front;
north = back;
west = right;
east = left;
top = down;
bottom = up;
}
case WEST -> {
west = front;
east = back;
north = right;
south = left;
top = left;
bottom = left;
}
case EAST -> {
east = front;
west = back;
north = left;
south = right;
top = right;
bottom = right;
}
}
return new ResourceLocation[]{bottom, top, north, south, east, west};
}
}