starting work on modeling. oh god. why.
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)));
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 497 B |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 484 B |
After Width: | Height: | Size: 484 B |
After Width: | Height: | Size: 341 B |
After Width: | Height: | Size: 308 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 379 B |
|
@ -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};
|
||||
}
|
||||
|
||||
}
|
||||
|
|