Compare commits

..

No commits in common. "d43d9456ee47d94c5a4aa255cc19a6cf4a88be31" and "2957a899db5639ddcb440c0c92a5348ccba9b249" have entirely different histories.

129 changed files with 3956 additions and 1210 deletions

View File

@ -9,7 +9,7 @@ loader_version=0.15.6
# Mod Properties # Mod Properties
modrinth_id = jCpoCBpn modrinth_id = jCpoCBpn
mod_version = 1.4 mod_version = 1.3.5
maven_group = fr.adrien1106 maven_group = fr.adrien1106
archives_base_name = ReFramed archives_base_name = ReFramed
mod_id = reframed mod_id = reframed

View File

@ -1,21 +1,20 @@
package fr.adrien1106.reframed; package fr.adrien1106.reframed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import fr.adrien1106.reframed.block.*; import fr.adrien1106.reframed.block.*;
import fr.adrien1106.reframed.util.BlockHelper;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.minecraft.block.AbstractBlock; import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -26,14 +25,13 @@ import java.util.function.BiConsumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* TODO self culling, fix other models, better connected textures, preload items, better cache * TODO self culling, fix other models, better connected textures, preload items
*/ */
public class ReFramed implements ModInitializer { public class ReFramed implements ModInitializer {
public static final String MODID = "reframed"; public static final String MODID = "reframed";
public static final ArrayList<Block> BLOCKS = new ArrayList<>(); public static final ArrayList<Block> BLOCKS = new ArrayList<>();
public static Block CUBE, STAIRS, DOUBLE_STAIRS, SLAB, DOUBLE_SLAB, STEP, DOUBLE_STEP; public static Block CUBE, STAIRS, DOUBLE_STAIRS, SLAB, DOUBLE_SLAB, POST, FENCE, FENCE_GATE, DOOR, TRAPDOOR, IRON_DOOR, IRON_TRAPDOOR, PRESSURE_PLATE, BUTTON, LEVER, WALL, CARPET, PANE, CANDLE;
public static ItemGroup ITEM_GROUP;
public static BlockEntityType<ReFramedEntity> REFRAMED_BLOCK_ENTITY; public static BlockEntityType<ReFramedEntity> REFRAMED_BLOCK_ENTITY;
public static BlockEntityType<ReFramedDoubleEntity> REFRAMED_DOUBLE_BLOCK_ENTITY; public static BlockEntityType<ReFramedDoubleEntity> REFRAMED_DOUBLE_BLOCK_ENTITY;
@ -47,13 +45,25 @@ public class ReFramed implements ModInitializer {
//corresponding vanilla block in the "search" creative tab... with the non-vanilla "post" and //corresponding vanilla block in the "search" creative tab... with the non-vanilla "post" and
//"vertical slab" inserted where they fit ...and i moved the lever way up next to the pressureplate //"vertical slab" inserted where they fit ...and i moved the lever way up next to the pressureplate
//and button, because they're redstoney... hopefully this ordering makes sense lol //and button, because they're redstoney... hopefully this ordering makes sense lol
CUBE = registerReFramed("cube" , new ReFramedBlock(cp(Blocks.OAK_PLANKS))); CUBE = registerReFramed("cube" , new ReFramedBlock(ReFramedInteractionUtil.makeSettings()));
STAIRS = registerReFramed("stairs" , new ReFramedStairsBlock(cp(Blocks.OAK_STAIRS))); STAIRS = registerReFramed("stairs" , new ReFramedStairsBlock(cp(Blocks.OAK_STAIRS)));
DOUBLE_STAIRS = registerReFramed("double_stairs" , new ReFramedDoubleStairsBlock(cp(Blocks.OAK_STAIRS))); DOUBLE_STAIRS = registerReFramed("double_stairs" , new ReFramedDoubleStairsBlock(cp(Blocks.OAK_STAIRS)));
SLAB = registerReFramed("slab" , new ReFramedSlabBlock(cp(Blocks.OAK_SLAB))); SLAB = registerReFramed("slab" , new ReFramedSlabBlock(cp(Blocks.OAK_SLAB)));
DOUBLE_SLAB = registerReFramed("double_slab" , new ReFramedDoubleSlabBlock(cp(Blocks.OAK_SLAB))); DOUBLE_SLAB = registerReFramed("double_slab" , new ReFramedDoubleSlabBlock(cp(Blocks.OAK_SLAB)));
STEP = registerReFramed("step" , new ReFramedStepBlock(cp(Blocks.OAK_SLAB))); POST = registerReFramed("post" , new ReFramedPostBlock(cp(Blocks.OAK_FENCE)));
DOUBLE_STEP = registerReFramed("double_step" , new ReFramedDoubleStepBlock(cp(Blocks.OAK_SLAB))); FENCE = registerReFramed("fence" , new ReFramedFenceBlock(cp(Blocks.OAK_FENCE)));
FENCE_GATE = registerReFramed("fence_gate" , new ReFramedFenceGateBlock(cp(Blocks.OAK_FENCE_GATE)));
DOOR = registerReFramed("door" , new ReFramedDoorBlock(cp(Blocks.OAK_DOOR), BlockSetType.OAK));
TRAPDOOR = registerReFramed("trapdoor" , new ReFramedTrapdoorBlock(cp(Blocks.OAK_TRAPDOOR), BlockSetType.OAK));
IRON_DOOR = registerReFramed("iron_door" , new ReFramedDoorBlock(cp(Blocks.IRON_DOOR), BlockSetType.IRON));
IRON_TRAPDOOR = registerReFramed("iron_trapdoor" , new ReFramedTrapdoorBlock(cp(Blocks.IRON_TRAPDOOR), BlockSetType.IRON));
PRESSURE_PLATE = registerReFramed("pressure_plate", new ReFramedPressurePlateBlock(cp(Blocks.OAK_PRESSURE_PLATE)));
BUTTON = registerReFramed("button" , new ReFramedButtonBlock(cp(Blocks.OAK_BUTTON)));
LEVER = registerReFramed("lever" , new ReFramedLeverBlock(cp(Blocks.LEVER)));
WALL = registerReFramed("wall" , new ReFramedWallBlock(ReFramedInteractionUtil.makeSettings()));
CARPET = registerReFramed("carpet" , new ReFramedCarpetBlock(cp(Blocks.WHITE_CARPET)));
PANE = registerReFramed("pane" , new ReFramedPaneBlock(cp(Blocks.GLASS_PANE)));
CANDLE = registerReFramed("candle" , new ReFramedCandleBlock(ReFramedCandleBlock.configureSettings(cp(Blocks.CANDLE))));
REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"), REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"),
FabricBlockEntityTypeBuilder.create( FabricBlockEntityTypeBuilder.create(
@ -71,7 +81,7 @@ public class ReFramed implements ModInitializer {
.toArray(Block[]::new)).build(null) .toArray(Block[]::new)).build(null)
); );
ITEM_GROUP = Registry.register(Registries.ITEM_GROUP, id("tab"), FabricItemGroup.builder() Registry.register(Registries.ITEM_GROUP, id("tab"), FabricItemGroup.builder()
.displayName(Text.translatable("itemGroup.reframed.tab")) .displayName(Text.translatable("itemGroup.reframed.tab"))
.icon(() -> new ItemStack(SLAB)) .icon(() -> new ItemStack(SLAB))
.entries((ctx, e) -> e.addAll(BLOCKS.stream().map(ItemStack::new).collect(Collectors.toList()))).build() .entries((ctx, e) -> e.addAll(BLOCKS.stream().map(ItemStack::new).collect(Collectors.toList()))).build()
@ -79,13 +89,7 @@ public class ReFramed implements ModInitializer {
} }
private static AbstractBlock.Settings cp(Block base) { private static AbstractBlock.Settings cp(Block base) {
return AbstractBlock.Settings.copy(base) return ReFramedInteractionUtil.configureSettings(AbstractBlock.Settings.copy(base));
.luminance(BlockHelper::luminance)
.nonOpaque()
.sounds(BlockSoundGroup.WOOD)
.hardness(0.2f)
.suffocates((a,b,c) -> false)
.blockVision((a,b,c) -> false);
} }
private static <B extends Block> B registerReFramed(String path, B block) { private static <B extends Block> B registerReFramed(String path, B block) {

View File

@ -1,26 +1,23 @@
package fr.adrien1106.reframed.block; package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.RecipeSetter; import fr.adrien1106.reframed.util.ReframedInteractible;
import fr.adrien1106.reframed.util.BlockHelper; import fr.adrien1106.reframed.util.ThemeableBlockEntity;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.*;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.recipe.book.RecipeCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer; import net.minecraft.util.ItemScatterer;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
@ -33,9 +30,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import static fr.adrien1106.reframed.util.BlockProperties.LIGHT; import static net.minecraft.util.shape.VoxelShapes.*;
public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeSetter { public class ReFramedBlock extends Block implements BlockEntityProvider {
public static final BooleanProperty LIGHT = BooleanProperty.of("frame_light");
public ReFramedBlock(Settings settings) { public ReFramedBlock(Settings settings) {
super(settings); super(settings);
@ -63,9 +62,9 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
@Override @Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!canUse(world, pos, player)) return superUse(state, world, pos, player, hand, hit); if (!canUse(world, pos, player)) return superUse(state, world, pos, player, hand, hit);
ActionResult result = BlockHelper.useUpgrade(state, world, pos, player, hand); ActionResult result = useUpgrade(state, world, pos, player, hand);
if (result.isAccepted()) return result; if (result.isAccepted()) return result;
return BlockHelper.useCamo(state, world, pos, player, hand, hit, 1); return useCamo(state, world, pos, player, hand, hit, 1);
} }
@ -78,6 +77,85 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
return player.canModifyBlocks() && world.canPlayerModifyAt(player, pos); return player.canModifyBlocks() && world.canPlayerModifyAt(player, pos);
} }
protected static ActionResult useUpgrade(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand) {
if(!(world.getBlockEntity(pos) instanceof ReFramedEntity block_entity)) return ActionResult.PASS;
ItemStack held = player.getStackInHand(hand);
ReframedInteractible ext = state.getBlock() instanceof ReframedInteractible e ? e : ReframedInteractible.Default.INSTANCE;
// frame will emit light if applied with glowstone
if(state.contains(LIGHT) && held.getItem() == Items.GLOWSTONE_DUST) {
block_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
if(!player.isCreative())
if (block_entity.emitsLight()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.BLOCK_GLASS_HIT, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// frame will emit redstone if applied with redstone torch can deactivate redstone block camo emission
if(held.getItem() == Items.REDSTONE_TORCH && ext.canAddRedstoneEmission(state, world, pos)) {
block_entity.toggleRedstone();
if(!player.isCreative())
if (block_entity.emitsRedstone()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// Frame will lose its collision if applied with popped chorus fruit
if(held.getItem() == Items.POPPED_CHORUS_FRUIT && ext.canRemoveCollision(state, world, pos)) {
block_entity.toggleSolidity();
if(!player.isCreative())
if (!block_entity.isSolid()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
protected static ActionResult useCamo(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, int theme_index) {
if(!(world.getBlockEntity(pos) instanceof ReFramedEntity block_entity)) return ActionResult.PASS;
// Changing the theme
ItemStack held = player.getStackInHand(hand);
if(held.getItem() instanceof BlockItem block_item && block_entity.getTheme(theme_index).getBlock() == Blocks.AIR) {
Block block = block_item.getBlock();
ItemPlacementContext ctx = new ItemPlacementContext(new ItemUsageContext(player, hand, hit));
BlockState placement_state = block.getPlacementState(ctx);
if(placement_state != null && isShapeFullCube(placement_state.getCollisionShape(world, pos)) && !(block instanceof BlockEntityProvider)) {
List<BlockState> themes = block_entity.getThemes();
if(!world.isClient) block_entity.setTheme(placement_state, theme_index);
// check for default light emission
if (placement_state.getLuminance() > 0
&& themes.stream().noneMatch(theme -> theme.getLuminance() > 0))
if (block_entity.emitsLight()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
else block_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
// check for default redstone emission
if (placement_state.getWeakRedstonePower(world, pos, Direction.NORTH) > 0
&& themes.stream().noneMatch(theme -> theme.getWeakRedstonePower(world, pos, Direction.NORTH) > 0))
if (block_entity.emitsRedstone()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
else block_entity.toggleRedstone();
if(!player.isCreative()) held.decrement(1);
world.playSound(player, pos, placement_state.getSoundGroup().getPlaceSound(), SoundCategory.BLOCKS, 1f, 1.1f);
return ActionResult.SUCCESS;
}
}
return ActionResult.PASS;
}
@Override @Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if(!state.isOf(newState.getBlock()) && if(!state.isOf(newState.getBlock()) &&
@ -152,17 +230,82 @@ public class ReFramedBlock extends Block implements BlockEntityProvider, RecipeS
return 1; return 1;
} }
@Override // Doing this method from scratch as it is simpler to do than injecting everywhere
public void setRecipe(RecipeExporter exporter) { public static boolean shouldDrawSide(BlockState self_state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, int theme_index) {
ShapedRecipeJsonBuilder ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e ? e : null;
.create(RecipeCategory.BUILDING_BLOCKS, this) ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e ? e : null;
.pattern("III") BlockState other_state = world.getBlockState(other_pos);
.pattern("I~I")
.pattern("III") // normal behaviour
.input('I', Items.BAMBOO) if (self == null && other == null) return shouldDrawSide(self_state, world, pos, side, other_pos);
.input('~', Items.STRING)
.criterion(FabricRecipeProvider.hasItem(Items.BAMBOO), FabricRecipeProvider.conditionsFromItem(Items.BAMBOO)) // self is a normal Block
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this)) if (self == null && other_state.getBlock() instanceof ReFramedBlock other_block) {
.offerTo(exporter); VoxelShape self_shape = self_state.getCullingShape(world, pos);
if (self_shape.isEmpty()) return true;
int i = 0;
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_state.isSideInvisible(s, side) || s.isOpaque())
other_shape = combine(
other_shape,
other_block
.getShape(other_state, i)
.getFace(side.getOpposite()),
BooleanBiFunction.OR
);
}
// determine if side needs to be rendered
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
}
BlockState self_theme = self.getTheme(theme_index);
// other is normal Block
if (other == null && self_state.getBlock() instanceof ReFramedBlock self_block) {
// Transparent is simple if self and the neighbor are invisible don't render side (like default)
if (self_theme.isSideInvisible(other_state, side)) return false;
// Opaque is also simple as each model are rendered one by one
if (other_state.isOpaque()) {
// no cache section :( because it differs between each instance of the frame
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
if (self_shape.isEmpty()) return true;
VoxelShape other_shape = other_state.getCullingFace(world, other_pos, side.getOpposite());
// determine if side needs to be rendered
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
}
return true;
}
// Both are frames
// here both are computed in the same zone as there will necessarily a shape comparison
if (self_state.getBlock() instanceof ReFramedBlock self_block && other_state.getBlock() instanceof ReFramedBlock other_block) {
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
if (self_shape.isEmpty()) return true;
int i = 0;
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
other_shape = combine(
other_shape,
other_block
.getShape(other_state, i)
.getFace(side.getOpposite()),
BooleanBiFunction.OR
);
}
// determine if side needs to be rendered
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
}
return true;
} }
} }

View File

@ -0,0 +1,95 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.BlockState;
import net.minecraft.block.ButtonBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedButtonBlock extends ButtonBlock implements BlockEntityProvider {
public ReFramedButtonBlock(Settings settings) {
this(settings, BlockSetType.OAK, 30);
}
public ReFramedButtonBlock(Settings settings, BlockSetType blockSetType, int i) {
super(blockSetType, i, settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return super.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
boolean a = 0 != super.getWeakRedstonePower(state, view, pos, dir);
boolean b = 0 != ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
return (a ^ b) ? 15 : 0;
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
if(getDirection(state) != dir) return 0;
else return getWeakRedstonePower(state, view, pos, dir);
}
}

View File

@ -0,0 +1,92 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.CandleBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedCandleBlock extends CandleBlock implements BlockEntityProvider {
public ReFramedCandleBlock(Settings settings) {
super(settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
public static AbstractBlock.Settings configureSettings(AbstractBlock.Settings in) {
return in.luminance(state -> Math.max(ReFramedInteractionUtil.luminance(state), CandleBlock.STATE_TO_LUMINANCE.applyAsInt(state)));
}
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
super.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
}

View File

@ -0,0 +1,87 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.CarpetBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedCarpetBlock extends CarpetBlock implements BlockEntityProvider {
public ReFramedCarpetBlock(Settings settings) {
super(settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
}

View File

@ -0,0 +1,89 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.BlockState;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedDoorBlock extends DoorBlock implements BlockEntityProvider {
public ReFramedDoorBlock(Settings settings, BlockSetType blockSetType) {
super(blockSetType, settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
super.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
}

View File

@ -1,7 +1,6 @@
package fr.adrien1106.reframed.block; package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.BlockHelper;
import fr.adrien1106.reframed.util.ThemeableBlockEntity; import fr.adrien1106.reframed.util.ThemeableBlockEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
@ -18,6 +17,10 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import static net.minecraft.util.shape.VoxelShapes.empty; import static net.minecraft.util.shape.VoxelShapes.empty;
import static net.minecraft.util.shape.VoxelShapes.fullCube; import static net.minecraft.util.shape.VoxelShapes.fullCube;
@ -31,7 +34,7 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
return ReFramed.REFRAMED_DOUBLE_BLOCK_ENTITY.instantiate(pos, state); return ReFramed.REFRAMED_DOUBLE_BLOCK_ENTITY.instantiate(pos, state);
} }
protected int getHitShape(BlockState state, BlockHitResult hit) { protected int getHitPart(BlockState state, BlockHitResult hit) {
Direction side = hit.getSide(); Direction side = hit.getSide();
VoxelShape first_shape = getShape(state, 1); VoxelShape first_shape = getShape(state, 1);
VoxelShape second_shape = getShape(state, 2); VoxelShape second_shape = getShape(state, 2);
@ -40,13 +43,29 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
if (isFaceFullSquare(first_shape, side)) return 1; if (isFaceFullSquare(first_shape, side)) return 1;
if (isFaceFullSquare(second_shape, side)) return 2; if (isFaceFullSquare(second_shape, side)) return 2;
Vec3d pos = BlockHelper.getRelativePos(hit.getPos(), hit.getBlockPos()); Vec3d pos = hit.getPos();
// System.out.println(side.getAxis().choose(hit.getPos().x, hit.getPos().y, hit.getPos().z)); BlockPos origin = hit.getBlockPos();
if (BlockHelper.cursorMatchesFace(first_shape, pos)) return 1; Map<Direction.Axis, Double> axes = Arrays.stream(Direction.Axis.values())
if (BlockHelper.cursorMatchesFace(second_shape, pos)) return 2; .filter(axis -> axis != side.getAxis())
.collect(Collectors.toMap(
axis -> axis,
axis -> axis.choose(pos.getX() - origin.getX(), pos.getY() - origin.getY(), pos.getZ() - origin.getZ()))
);
if (matchesFace(first_shape.getFace(side), axes)) return 1;
if (matchesFace(second_shape.getFace(side), axes)) return 2;
return 0; return 0;
} }
private static boolean matchesFace(VoxelShape shape, Map<Direction.Axis, Double> axes) {
return shape.getBoundingBoxes().stream()
.anyMatch(box ->
axes.keySet().stream()
.map(axis -> box.getMin(axis) <= axes.get(axis) && box.getMax(axis) >= axes.get(axis))
.reduce((prev, current) -> prev && current).get()
);
}
@Override @Override
public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) {
return world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity return world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
@ -54,12 +73,12 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
} }
public VoxelShape getRenderOutline(BlockState state, BlockHitResult hit) { public VoxelShape getRenderOutline(BlockState state, BlockHitResult hit) {
return getShape(state, getHitShape(state, hit)); return getShape(state, getHitPart(state, hit));
} }
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return getCullingShape(state, view, pos); return isGhost(view, pos) ? empty() : fullCube();
} }
@Override @Override
@ -70,8 +89,8 @@ public abstract class ReFramedDoubleBlock extends ReFramedBlock {
@Override @Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!canUse(world, pos, player)) return superUse(state, world, pos, player, hand, hit); if (!canUse(world, pos, player)) return superUse(state, world, pos, player, hand, hit);
ActionResult result = BlockHelper.useUpgrade(state, world, pos, player, hand); ActionResult result = useUpgrade(state, world, pos, player, hand);
if (result.isAccepted()) return result; if (result.isAccepted()) return result;
return BlockHelper.useCamo(state, world, pos, player, hand, hit, getHitShape(state, hit)); return useCamo(state, world, pos, player, hand, hit, getHitPart(state, hit));
} }
} }

View File

@ -1,17 +1,12 @@
package fr.adrien1106.reframed.block; package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.GBlockstate; import fr.adrien1106.reframed.generator.GBlockstate;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import fr.adrien1106.reframed.generator.MultipartBlockStateProvider;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.data.client.MultipartBlockStateSupplier; import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.state.property.Properties; import net.minecraft.state.property.Properties;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -20,11 +15,10 @@ import net.minecraft.util.shape.VoxelShape;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.*; import static fr.adrien1106.reframed.block.ReFramedSlabBlock.*;
import static net.minecraft.data.client.VariantSettings.Rotation.R0; import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.data.client.VariantSettings.Rotation.R90;
import static net.minecraft.state.property.Properties.AXIS; import static net.minecraft.state.property.Properties.AXIS;
public class ReFramedDoubleSlabBlock extends ReFramedDoubleBlock implements BlockStateProvider { public class ReFramedDoubleSlabBlock extends ReFramedDoubleBlock implements MultipartBlockStateProvider {
public ReFramedDoubleSlabBlock(Settings settings) { public ReFramedDoubleSlabBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(Properties.AXIS, Direction.Axis.Y)); setDefaultState(getDefaultState().with(Properties.AXIS, Direction.Axis.Y));
@ -67,15 +61,4 @@ public class ReFramedDoubleSlabBlock extends ReFramedDoubleBlock implements Bloc
.with(GBlockstate.when(AXIS, Direction.Axis.X), .with(GBlockstate.when(AXIS, Direction.Axis.X),
GBlockstate.variant(model_id, true, R90, R90)); GBlockstate.variant(model_id, true, R90, R90));
} }
@Override
public void setRecipe(RecipeExporter exporter) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, this)
.input(ReFramed.SLAB, 2)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
.offerTo(exporter);
}
} }

View File

@ -1,19 +1,12 @@
package fr.adrien1106.reframed.block; package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.generator.MultipartBlockStateProvider;
import fr.adrien1106.reframed.generator.BlockStateProvider; import fr.adrien1106.reframed.util.property.StairDirection;
import fr.adrien1106.reframed.util.BlockHelper;
import fr.adrien1106.reframed.util.property.Corner;
import fr.adrien1106.reframed.util.property.StairShape; import fr.adrien1106.reframed.util.property.StairShape;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.data.client.MultipartBlockStateSupplier; import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.util.function.BooleanBiFunction; import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -28,37 +21,33 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import static fr.adrien1106.reframed.block.ReFramedStairsBlock.*; import static fr.adrien1106.reframed.block.ReFramedStairsBlock.*;
import static fr.adrien1106.reframed.util.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.BlockProperties.STAIR_SHAPE;
import static fr.adrien1106.reframed.util.property.StairShape.STRAIGHT; import static fr.adrien1106.reframed.util.property.StairShape.STRAIGHT;
public class ReFramedDoubleStairsBlock extends ReFramedDoubleBlock implements BlockStateProvider { public class ReFramedDoubleStairsBlock extends ReFramedDoubleBlock implements MultipartBlockStateProvider {
private static final List<VoxelShape> COMPLEMENT_LIST = new ArrayList<>(52); private static final List<VoxelShape> COMPLEMENT_LIST = new ArrayList<>(52);
public ReFramedDoubleStairsBlock(Settings settings) { public ReFramedDoubleStairsBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(CORNER, Corner.NORTH_DOWN).with(STAIR_SHAPE, STRAIGHT)); setDefaultState(getDefaultState().with(FACING, StairDirection.NORTH_DOWN).with(SHAPE, STRAIGHT));
} }
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER, STAIR_SHAPE)); super.appendProperties(builder.add(FACING).add(SHAPE));
} }
@Override @Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighbor_state, WorldAccess world, BlockPos pos, BlockPos moved) { public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighbor_state, WorldAccess world, BlockPos pos, BlockPos moved) {
return super.getStateForNeighborUpdate(state, direction, neighbor_state, world, pos, moved) return super.getStateForNeighborUpdate(state, direction, neighbor_state, world, pos, moved)
.with(STAIR_SHAPE, BlockHelper.getStairsShape(this, state.get(CORNER), world, pos)); .with(SHAPE, getPlacementShape(this, state.get(FACING), world, pos));
} }
@Nullable @Nullable
@Override @Override
public BlockState getPlacementState(ItemPlacementContext ctx) { public BlockState getPlacementState(ItemPlacementContext ctx) {
Corner face = BlockHelper.getPlacementCorner(ctx); return getPlacement(super.getPlacementState(ctx), ctx);
StairShape shape = BlockHelper.getStairsShape(this, face, ctx.getWorld(), ctx.getBlockPos());
return super.getPlacementState(ctx).with(CORNER, face).with(STAIR_SHAPE, shape);
} }
@Override @Override
@ -74,8 +63,8 @@ public class ReFramedDoubleStairsBlock extends ReFramedDoubleBlock implements Bl
} }
private VoxelShape getComplementOutline(BlockState state) { private VoxelShape getComplementOutline(BlockState state) {
StairShape shape = state.get(STAIR_SHAPE); StairShape shape = state.get(SHAPE);
Corner direction = state.get(CORNER); StairDirection direction = state.get(FACING);
return switch (shape) { return switch (shape) {
case STRAIGHT -> case STRAIGHT ->
switch (direction) { switch (direction) {
@ -192,18 +181,6 @@ public class ReFramedDoubleStairsBlock extends ReFramedDoubleBlock implements Bl
return getStairMultipart(this, true); return getStairMultipart(this, true);
} }
@Override
public void setRecipe(RecipeExporter exporter) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, this)
.input(ReFramed.STAIRS)
.input(ReFramed.STEP)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
.offerTo(exporter);
}
static { static {
VOXEL_LIST.forEach(shape -> COMPLEMENT_LIST.add(VoxelShapes.combineAndSimplify(VoxelShapes.fullCube(), shape, BooleanBiFunction.ONLY_FIRST))); VOXEL_LIST.forEach(shape -> COMPLEMENT_LIST.add(VoxelShapes.combineAndSimplify(VoxelShapes.fullCube(), shape, BooleanBiFunction.ONLY_FIRST)));
} }

View File

@ -1,118 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.GBlockstate;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.util.BlockHelper;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import static fr.adrien1106.reframed.block.ReFramedSlabBlock.*;
import static fr.adrien1106.reframed.block.ReFramedStepBlock.STEP_VOXELS;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.FACING;
import static net.minecraft.state.property.Properties.AXIS;
import static net.minecraft.util.shape.VoxelShapes.empty;
public class ReFramedDoubleStepBlock extends WaterloggableReFramedDoubleBlock implements BlockStateProvider {
public ReFramedDoubleStepBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(FACING, Direction.DOWN).with(AXIS, Axis.X));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING, AXIS));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
Vec3d pos = BlockHelper.getHitPos(ctx.getHitPos(), ctx.getBlockPos());
return super.getPlacementState(ctx)
.with(FACING, ctx.getSide().getOpposite())
.with(AXIS, BlockHelper.getHitAxis(pos, ctx.getSide()));
}
@Override
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
return isGhost(view, pos) ? empty() : getSlabShape(state.get(FACING));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabShape(state.get(FACING));
}
@Override
public VoxelShape getShape(BlockState state, int i) {
Axis axis = state.get(AXIS);
return STEP_VOXELS.get(switch (state.get(FACING)) {
case DOWN -> axis == Axis.Z ? (i == 1 ? 0 : 1): (i == 1 ? 4 : 5 );
case UP -> axis == Axis.Z ? (i == 1 ? 3 : 2): (i == 1 ? 7 : 6 );
case NORTH -> axis == Axis.Y ? (i == 1 ? 1 : 2): (i == 1 ? 11 : 8 );
case SOUTH -> axis == Axis.Y ? (i == 1 ? 0 : 3): (i == 1 ? 9 : 10);
case EAST -> axis == Axis.Y ? (i == 1 ? 4 : 7): (i == 1 ? 8 : 9 );
case WEST -> axis == Axis.Y ? (i == 1 ? 5 : 6): (i == 1 ? 10 : 11);
});
}
@Override
public MultipartBlockStateSupplier getMultipart() {
Identifier step_id = ReFramed.id("double_step_special");
Identifier step_side_id = ReFramed.id("double_step_side_special");
return MultipartBlockStateSupplier.create(this)
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Axis.X),
GBlockstate.variant(step_id, true, R0, R0))
.with(GBlockstate.when(FACING, Direction.DOWN, AXIS, Axis.Z),
GBlockstate.variant(step_id, true, R0, R90))
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Axis.X),
GBlockstate.variant(step_id, true, R180, R0))
.with(GBlockstate.when(FACING, Direction.UP, AXIS, Axis.Z),
GBlockstate.variant(step_id, true, R180, R90))
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Axis.Z),
GBlockstate.variant(step_side_id, true, R0, R0))
.with(GBlockstate.when(FACING, Direction.EAST, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R0))
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Axis.X),
GBlockstate.variant(step_side_id, true, R0, R90))
.with(GBlockstate.when(FACING, Direction.SOUTH, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R90))
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Axis.Z),
GBlockstate.variant(step_side_id, true, R0, R180))
.with(GBlockstate.when(FACING, Direction.WEST, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R180))
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Axis.X),
GBlockstate.variant(step_side_id, true, R0, R270))
.with(GBlockstate.when(FACING, Direction.NORTH, AXIS, Axis.Y),
GBlockstate.variant(step_side_id, true, R90, R270));
}
@Override
public void setRecipe(RecipeExporter exporter) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
ShapelessRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, this)
.input(ReFramed.STEP, 2)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
.offerTo(exporter);
}
}

View File

@ -1,7 +1,6 @@
package fr.adrien1106.reframed.block; package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.BlockProperties;
import fr.adrien1106.reframed.util.ThemeableBlockEntity; import fr.adrien1106.reframed.util.ThemeableBlockEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -88,8 +87,8 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
NbtCompound nbt = BlockItem.getBlockEntityNbt(stack); NbtCompound nbt = BlockItem.getBlockEntityNbt(stack);
if(nbt == null) return state; if(nbt == null) return state;
if(state.contains(BlockProperties.LIGHT)) { if(state.contains(ReFramedBlock.LIGHT)) {
state = state.with(BlockProperties.LIGHT, state = state.with(ReFramedBlock.LIGHT,
((nbt.contains(BITFIELD_KEY) ((nbt.contains(BITFIELD_KEY)
? nbt.getByte(BITFIELD_KEY) ? nbt.getByte(BITFIELD_KEY)
: SOLIDITY_MASK) : SOLIDITY_MASK)

View File

@ -0,0 +1,87 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedFenceBlock extends FenceBlock implements BlockEntityProvider {
public ReFramedFenceBlock(Settings settings) {
super(settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
}

View File

@ -0,0 +1,98 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import fr.adrien1106.reframed.util.ReframedInteractible;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceGateBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.WoodType;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedFenceGateBlock extends FenceGateBlock implements BlockEntityProvider, ReframedInteractible {
public ReFramedFenceGateBlock(Settings settings, WoodType woodType) {
super(woodType, settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
public ReFramedFenceGateBlock(Settings settings) {
this(settings, WoodType.OAK);
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
@Override
public boolean canAddRedstoneEmission(BlockState state, BlockView view, BlockPos pos) {
return false;
}
}

View File

@ -0,0 +1,90 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.LeverBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedLeverBlock extends LeverBlock implements BlockEntityProvider {
public ReFramedLeverBlock(Settings settings) {
super(settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return super.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
boolean a = 0 != super.getWeakRedstonePower(state, view, pos, dir);
boolean b = 0 != ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
return (a ^ b) ? 15 : 0;
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
if(getDirection(state) != dir) return 0;
else return getWeakRedstonePower(state, view, pos, dir);
}
}

View File

@ -0,0 +1,87 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.PaneBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedPaneBlock extends PaneBlock implements BlockEntityProvider {
public ReFramedPaneBlock(Settings settings) {
super(settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
super.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
}

View File

@ -0,0 +1,57 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
public class ReFramedPostBlock extends WaterloggableReFramedBlock {
public ReFramedPostBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(Properties.AXIS, Direction.Axis.Y));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(Properties.AXIS));
}
@Override
public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState sup = super.getPlacementState(ctx);
if(sup != null) sup = sup.with(Properties.AXIS, ctx.getSide().getAxis());
return sup;
}
protected static final VoxelShape SHAPE_X = createCuboidShape(0, 6, 6, 16, 10, 10);
protected static final VoxelShape SHAPE_Y = createCuboidShape(6, 0, 6, 10, 16, 10);
protected static final VoxelShape SHAPE_Z = createCuboidShape(6, 6, 0, 10, 10, 16);
protected VoxelShape shap(BlockState state) {
return switch(state.get(Properties.AXIS)) {
case X -> SHAPE_X;
case Y -> SHAPE_Y;
case Z -> SHAPE_Z;
};
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), shap(state));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return shap(state);
}
}

View File

@ -0,0 +1,89 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedPressurePlateBlock extends PressurePlateBlock implements BlockEntityProvider {
public ReFramedPressurePlateBlock(Settings settings, BlockSetType blockSetType) {
super(blockSetType, settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
public ReFramedPressurePlateBlock(Settings settings) {
this(settings, BlockSetType.OAK);
}
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
super.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return super.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
boolean a = 0 != super.getWeakRedstonePower(state, view, pos, dir);
boolean b = 0 != ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
return (a ^ b) ? 15 : 0;
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return dir == Direction.UP ? getWeakRedstonePower(state, view, pos, dir) : 0;
}
}

View File

@ -1,18 +1,13 @@
package fr.adrien1106.reframed.block; package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.generator.GBlockstate; import fr.adrien1106.reframed.generator.GBlockstate;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import fr.adrien1106.reframed.generator.MultipartBlockStateProvider;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.data.client.MultipartBlockStateSupplier; import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -25,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
import static net.minecraft.data.client.VariantSettings.Rotation.*; import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static net.minecraft.state.property.Properties.FACING; import static net.minecraft.state.property.Properties.FACING;
public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements BlockStateProvider { public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements MultipartBlockStateProvider {
protected static final VoxelShape DOWN = VoxelShapes.cuboid(0f, 0f, 0f, 1f, 0.5f, 1f); protected static final VoxelShape DOWN = VoxelShapes.cuboid(0f, 0f, 0f, 1f, 0.5f, 1f);
protected static final VoxelShape UP = VoxelShapes.cuboid(0f, 0.5f, 0f, 1f, 1f, 1f); protected static final VoxelShape UP = VoxelShapes.cuboid(0f, 0.5f, 0f, 1f, 1f, 1f);
@ -52,11 +47,7 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements Blo
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return getSlabShape(state.get(FACING)); return switch (state.get(FACING)) {
}
public static VoxelShape getSlabShape(Direction side) {
return switch (side) {
case DOWN -> DOWN; case DOWN -> DOWN;
case UP -> UP; case UP -> UP;
case NORTH -> NORTH; case NORTH -> NORTH;
@ -83,16 +74,4 @@ public class ReFramedSlabBlock extends WaterloggableReFramedBlock implements Blo
.with(GBlockstate.when(FACING, Direction.EAST), .with(GBlockstate.when(FACING, Direction.EAST),
GBlockstate.variant(model_id, true, R90, R270)); GBlockstate.variant(model_id, true, R90, R270));
} }
@Override
public void setRecipe(RecipeExporter exporter) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 2);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, this, 6)
.pattern("III")
.input('I', ReFramed.CUBE)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
.offerTo(exporter);
}
} }

View File

@ -2,27 +2,23 @@ package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.GBlockstate; import fr.adrien1106.reframed.generator.GBlockstate;
import fr.adrien1106.reframed.generator.BlockStateProvider; import fr.adrien1106.reframed.generator.MultipartBlockStateProvider;
import fr.adrien1106.reframed.util.BlockHelper;
import fr.adrien1106.reframed.util.VoxelHelper; import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.property.Corner; import fr.adrien1106.reframed.util.property.StairDirection;
import fr.adrien1106.reframed.util.property.StairShape; import fr.adrien1106.reframed.util.property.StairShape;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.data.client.*; import net.minecraft.data.client.*;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.function.BooleanBiFunction; import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis; import net.minecraft.util.math.Direction.Axis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
@ -34,37 +30,64 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import static fr.adrien1106.reframed.util.BlockProperties.*;
import static fr.adrien1106.reframed.util.property.StairShape.*; import static fr.adrien1106.reframed.util.property.StairShape.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*; import static net.minecraft.data.client.VariantSettings.Rotation.*;
import static fr.adrien1106.reframed.util.property.Corner.*; import static fr.adrien1106.reframed.util.property.StairDirection.*;
public class ReFramedStairsBlock extends WaterloggableReFramedBlock implements BlockStateProvider { public class ReFramedStairsBlock extends WaterloggableReFramedBlock implements MultipartBlockStateProvider {
public static final EnumProperty<StairDirection> FACING = EnumProperty.of("facing", StairDirection.class);
public static final EnumProperty<StairShape> SHAPE = EnumProperty.of("shape", StairShape.class);
public static final List<VoxelShape> VOXEL_LIST = new ArrayList<>(52); public static final List<VoxelShape> VOXEL_LIST = new ArrayList<>(52);
public ReFramedStairsBlock(Settings settings) { public ReFramedStairsBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(CORNER, Corner.NORTH_DOWN).with(STAIR_SHAPE, STRAIGHT)); setDefaultState(getDefaultState().with(FACING, StairDirection.NORTH_DOWN).with(SHAPE, STRAIGHT));
} }
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER, STAIR_SHAPE)); super.appendProperties(builder.add(FACING).add(SHAPE));
} }
@Override @Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighbor_state, WorldAccess world, BlockPos pos, BlockPos moved) { public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighbor_state, WorldAccess world, BlockPos pos, BlockPos moved) {
return super.getStateForNeighborUpdate(state, direction, neighbor_state, world, pos, moved) return super.getStateForNeighborUpdate(state, direction, neighbor_state, world, pos, moved)
.with(STAIR_SHAPE, BlockHelper.getStairsShape(state.getBlock(), state.get(CORNER), world, pos)); .with(SHAPE, getPlacementShape(state.getBlock(), state.get(FACING), world, pos));
} }
@Nullable @Nullable
@Override // Pretty happy of how clean it is (also got it on first try :) ) @Override // Pretty happy of how clean it is (also got it on first try :) )
public BlockState getPlacementState(ItemPlacementContext ctx) { public BlockState getPlacementState(ItemPlacementContext ctx) {
Corner face = BlockHelper.getPlacementCorner(ctx); return getPlacement(super.getPlacementState(ctx), ctx);
StairShape shape = BlockHelper.getStairsShape(this, face, ctx.getWorld(), ctx.getBlockPos()); }
return super.getPlacementState(ctx).with(CORNER, face).with(STAIR_SHAPE, shape);
public static BlockState getPlacement(BlockState state, ItemPlacementContext ctx) {
Direction side = ctx.getSide().getOpposite();
BlockPos block_pos = ctx.getBlockPos();
Vec3d hit_pos = ctx.getHitPos();
Vec3d pos = new Vec3d(
hit_pos.getX() - block_pos.getX() - .5d,
hit_pos.getY() - block_pos.getY() - .5d,
hit_pos.getZ() - block_pos.getZ() - .5d
);
Stream<Axis> axes = Stream.of(Axis.values()).filter(axis -> !axis.equals(side.getAxis()));
Axis axis = axes.reduce((axis_1, axis_2) ->
Math.abs(axis_1.choose(pos.x, pos.y, pos.z)) > Math.abs(axis_2.choose(pos.x, pos.y, pos.z))
? axis_1
: axis_2
).get();
Direction part_direction = Direction.from(
axis,
axis.choose(pos.x, pos.y, pos.z) > 0
? Direction.AxisDirection.POSITIVE
: Direction.AxisDirection.NEGATIVE
);
StairDirection face = StairDirection.getByDirections(side, part_direction);
return state.with(FACING, face).with(SHAPE, getPlacementShape(state.getBlock(), face, ctx.getWorld(), block_pos));
} }
@Override @Override
@ -81,8 +104,8 @@ public class ReFramedStairsBlock extends WaterloggableReFramedBlock implements B
} }
public static VoxelShape getOutline(BlockState state) { public static VoxelShape getOutline(BlockState state) {
StairShape shape = state.get(STAIR_SHAPE); StairShape shape = state.get(SHAPE);
Corner direction = state.get(CORNER); StairDirection direction = state.get(FACING);
return switch (shape) { return switch (shape) {
case STRAIGHT -> case STRAIGHT ->
switch (direction) { switch (direction) {
@ -194,6 +217,54 @@ public class ReFramedStairsBlock extends WaterloggableReFramedBlock implements B
}; };
} }
public static String getNeighborPos(StairDirection face, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos, Block block) {
BlockState block_state = world.getBlockState(
pos.offset(reverse ? direction.getOpposite() : direction)
);
if (block_state.isOf(block) && block_state.get(FACING).hasDirection(reference)) {
if (block_state.get(FACING).hasDirection(face.getLeftDirection())) return "left";
else if (block_state.get(FACING).hasDirection(face.getRightDirection())) return "right";
}
return "";
}
public static StairShape getPlacementShape(Block block, StairDirection face, BlockView world, BlockPos pos) {
StairShape shape = STRAIGHT;
String sol = getNeighborPos(face, face.getFirstDirection(), true, face.getSecondDirection(), world, pos, block);
switch (sol) {
case "right": return INNER_RIGHT;
case "left": return INNER_LEFT;
}
sol = getNeighborPos(face, face.getSecondDirection(), true, face.getFirstDirection(), world, pos, block);
switch (sol) {
case "right": return INNER_RIGHT;
case "left": return INNER_LEFT;
}
sol = getNeighborPos(face, face.getFirstDirection(), false, face.getSecondDirection(), world, pos, block);
switch (sol) {
case "right" -> shape = FIRST_OUTER_RIGHT;
case "left" -> shape = FIRST_OUTER_LEFT;
}
sol = getNeighborPos(face, face.getSecondDirection(), false, face.getFirstDirection(), world, pos, block);
switch (sol) {
case "right" -> {
if (shape.equals(STRAIGHT)) shape = SECOND_OUTER_RIGHT;
else if (shape.equals(FIRST_OUTER_RIGHT)) shape = OUTER_RIGHT;
}
case "left" -> {
if (shape.equals(STRAIGHT)) shape = SECOND_OUTER_LEFT;
else if (shape.equals(FIRST_OUTER_LEFT)) shape = OUTER_LEFT;
}
}
return shape;
}
@Override @Override
public MultipartBlockStateSupplier getMultipart() { public MultipartBlockStateSupplier getMultipart() {
return getStairMultipart(this, false); return getStairMultipart(this, false);
@ -208,234 +279,220 @@ public class ReFramedStairsBlock extends WaterloggableReFramedBlock implements B
Identifier outer_side_id = ReFramed.id(prefix + "outer_side_stairs_special"); Identifier outer_side_id = ReFramed.id(prefix + "outer_side_stairs_special");
return MultipartBlockStateSupplier.create(block) return MultipartBlockStateSupplier.create(block)
/* STRAIGHT X AXIS */ /* STRAIGHT X AXIS */
.with(GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, DOWN_EAST, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R0, R0)) GBlockstate.variant(straight_id, true, R0, R0))
.with(GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, EAST_UP, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R180, R0)) GBlockstate.variant(straight_id, true, R180, R0))
.with(GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, UP_WEST, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R180, R180)) GBlockstate.variant(straight_id, true, R180, R180))
.with(GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, WEST_DOWN, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R0, R180)) GBlockstate.variant(straight_id, true, R0, R180))
/* STRAIGHT Y AXIS */ /* STRAIGHT Y AXIS */
.with(GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, EAST_SOUTH, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R90, R0)) GBlockstate.variant(straight_id, true, R90, R0))
.with(GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, SOUTH_WEST, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R90, R90)) GBlockstate.variant(straight_id, true, R90, R90))
.with(GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, WEST_NORTH, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R90, R180)) GBlockstate.variant(straight_id, true, R90, R180))
.with(GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, NORTH_EAST, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R90, R270)) GBlockstate.variant(straight_id, true, R90, R270))
/* STRAIGHT Z AXIS */ /* STRAIGHT Z AXIS */
.with(GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R0, R90)) GBlockstate.variant(straight_id, true, R0, R90))
.with(GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, NORTH_DOWN, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R0, R270)) GBlockstate.variant(straight_id, true, R0, R270))
.with(GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, UP_NORTH, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R180, R270)) GBlockstate.variant(straight_id, true, R180, R270))
.with(GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, STRAIGHT), .with(GBlockstate.when(FACING, SOUTH_UP, SHAPE, STRAIGHT),
GBlockstate.variant(straight_id, true, R180, R90)) GBlockstate.variant(straight_id, true, R180, R90))
/* INNER BOTTOM */ /* INNER BOTTOM */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, WEST_NORTH, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, INNER_LEFT)), GBlockstate.when(FACING, WEST_DOWN, SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R0, R180)) GBlockstate.variant(inner_id, true, R0, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, NORTH_EAST, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, INNER_LEFT)), GBlockstate.when(FACING, DOWN_EAST, SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R0, R270)) GBlockstate.variant(inner_id, true, R0, R270))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, INNER_RIGHT)), GBlockstate.when(FACING, DOWN_EAST, SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R0, R0)) GBlockstate.variant(inner_id, true, R0, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, INNER_RIGHT)), GBlockstate.when(FACING, WEST_DOWN, SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R0, R90)) GBlockstate.variant(inner_id, true, R0, R90))
/* INNER TOP */ /* INNER TOP */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, EAST_UP, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, NORTH_EAST, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, INNER_RIGHT)), GBlockstate.when(FACING, UP_NORTH, SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R180, R0)) GBlockstate.variant(inner_id, true, R180, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, INNER_RIGHT), GBlockstate.when(FACING, EAST_UP, SHAPE, INNER_RIGHT),
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, INNER_RIGHT)), GBlockstate.when(FACING, SOUTH_UP, SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R180, R90)) GBlockstate.variant(inner_id, true, R180, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, SOUTH_UP, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, INNER_RIGHT)), GBlockstate.when(FACING, UP_WEST, SHAPE, INNER_RIGHT)),
GBlockstate.variant(inner_id, true, R180, R180)) GBlockstate.variant(inner_id, true, R180, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, UP_NORTH, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, INNER_LEFT), GBlockstate.when(FACING, WEST_NORTH, SHAPE, INNER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, INNER_LEFT)), GBlockstate.when(FACING, UP_WEST, SHAPE, INNER_LEFT)),
GBlockstate.variant(inner_id, true, R180, R270)) GBlockstate.variant(inner_id, true, R180, R270))
/* OUTER BOTTOM */ /* OUTER BOTTOM */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT)), GBlockstate.when(FACING, DOWN_EAST, SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R0, R0)) GBlockstate.variant(outer_id, true, R0, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT)), GBlockstate.when(FACING, WEST_DOWN, SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R0, R90)) GBlockstate.variant(outer_id, true, R0, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, FIRST_OUTER_LEFT)), GBlockstate.when(FACING, WEST_DOWN, SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R0, R180)) GBlockstate.variant(outer_id, true, R0, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, FIRST_OUTER_RIGHT), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT)), GBlockstate.when(FACING, DOWN_EAST, SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R0, R270)) GBlockstate.variant(outer_id, true, R0, R270))
/* OUTER TOP */ /* OUTER TOP */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT), GBlockstate.when(FACING, UP_NORTH, SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, FIRST_OUTER_LEFT)), GBlockstate.when(FACING, EAST_UP, SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R180, R0)) GBlockstate.variant(outer_id, true, R180, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT), GBlockstate.when(FACING, SOUTH_UP, SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, FIRST_OUTER_RIGHT)), GBlockstate.when(FACING, EAST_UP, SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R180, R90)) GBlockstate.variant(outer_id, true, R180, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, FIRST_OUTER_LEFT), GBlockstate.when(FACING, SOUTH_UP, SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT)), GBlockstate.when(FACING, UP_WEST, SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_id, true, R180, R180)) GBlockstate.variant(outer_id, true, R180, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT), GBlockstate.when(FACING, UP_NORTH, SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT)), GBlockstate.when(FACING, UP_WEST, SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_id, true, R180, R270)) GBlockstate.variant(outer_id, true, R180, R270))
/* OUTER EAST */ /* OUTER EAST */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_RIGHT), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT)), GBlockstate.when(FACING, DOWN_EAST, SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R0, R0)) GBlockstate.variant(outer_side_id, true, R0, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, SECOND_OUTER_LEFT), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)), GBlockstate.when(FACING, EAST_UP, SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R90, R0)) GBlockstate.variant(outer_side_id, true, R90, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT), GBlockstate.when(FACING, NORTH_EAST, SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)), GBlockstate.when(FACING, EAST_UP, SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R180, R0)) GBlockstate.variant(outer_side_id, true, R180, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, FIRST_OUTER_RIGHT), GBlockstate.when(FACING, NORTH_EAST, SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, FIRST_OUTER_LEFT)), GBlockstate.when(FACING, DOWN_EAST, SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R270, R0)) GBlockstate.variant(outer_side_id, true, R270, R0))
/* OUTER SOUTH */ /* OUTER SOUTH */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, SECOND_OUTER_RIGHT), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, FIRST_OUTER_LEFT)), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R0, R90)) GBlockstate.variant(outer_side_id, true, R0, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, SECOND_OUTER_LEFT), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, SECOND_OUTER_LEFT)), GBlockstate.when(FACING, SOUTH_UP, SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R90, R90)) GBlockstate.variant(outer_side_id, true, R90, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, FIRST_OUTER_LEFT), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, SECOND_OUTER_RIGHT)), GBlockstate.when(FACING, SOUTH_UP, SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R180, R90)) GBlockstate.variant(outer_side_id, true, R180, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, FIRST_OUTER_RIGHT), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, FIRST_OUTER_RIGHT)), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R270, R90)) GBlockstate.variant(outer_side_id, true, R270, R90))
/* OUTER WEST */ /* OUTER WEST */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_RIGHT), GBlockstate.when(FACING, WEST_NORTH, SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)), GBlockstate.when(FACING, WEST_DOWN, SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R0, R180)) GBlockstate.variant(outer_side_id, true, R0, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, SECOND_OUTER_LEFT), GBlockstate.when(FACING, WEST_NORTH, SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT)), GBlockstate.when(FACING, UP_WEST, SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R90, R180)) GBlockstate.variant(outer_side_id, true, R90, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_LEFT), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT)), GBlockstate.when(FACING, UP_WEST, SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R180, R180)) GBlockstate.variant(outer_side_id, true, R180, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, FIRST_OUTER_RIGHT), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)), GBlockstate.when(FACING, WEST_DOWN, SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R270, R180)) GBlockstate.variant(outer_side_id, true, R270, R180))
/* OUTER NORTH */ /* OUTER NORTH */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, SECOND_OUTER_RIGHT), GBlockstate.when(FACING, NORTH_EAST, SHAPE, SECOND_OUTER_RIGHT),
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, SECOND_OUTER_RIGHT)), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, SECOND_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R0, R270)) GBlockstate.variant(outer_side_id, true, R0, R270))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, SECOND_OUTER_LEFT), GBlockstate.when(FACING, NORTH_EAST, SHAPE, SECOND_OUTER_LEFT),
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, FIRST_OUTER_RIGHT)), GBlockstate.when(FACING, UP_NORTH, SHAPE, FIRST_OUTER_RIGHT)),
GBlockstate.variant(outer_side_id, true, R90, R270)) GBlockstate.variant(outer_side_id, true, R90, R270))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, FIRST_OUTER_LEFT), GBlockstate.when(FACING, WEST_NORTH, SHAPE, FIRST_OUTER_LEFT),
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, FIRST_OUTER_LEFT)), GBlockstate.when(FACING, UP_NORTH, SHAPE, FIRST_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R180, R270)) GBlockstate.variant(outer_side_id, true, R180, R270))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, FIRST_OUTER_RIGHT), GBlockstate.when(FACING, WEST_NORTH, SHAPE, FIRST_OUTER_RIGHT),
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, SECOND_OUTER_LEFT)), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, SECOND_OUTER_LEFT)),
GBlockstate.variant(outer_side_id, true, R270, R270)) GBlockstate.variant(outer_side_id, true, R270, R270))
/* OUTER BOTTOM */ /* OUTER BOTTOM */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, DOWN_EAST, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, OUTER_RIGHT)), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R0)) GBlockstate.variant(double_outer_id, true, R0, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, DOWN_SOUTH, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, DOWN_SOUTH, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, WEST_DOWN, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, OUTER_RIGHT)), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R90)) GBlockstate.variant(double_outer_id, true, R0, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, WEST_DOWN, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, WEST_DOWN, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, OUTER_RIGHT)), GBlockstate.when(FACING, WEST_NORTH, SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R180)) GBlockstate.variant(double_outer_id, true, R0, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, NORTH_DOWN, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, NORTH_DOWN, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, DOWN_EAST, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, DOWN_EAST, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, OUTER_RIGHT)), GBlockstate.when(FACING, NORTH_EAST, SHAPE, OUTER_RIGHT)),
GBlockstate.variant(double_outer_id, true, R0, R270)) GBlockstate.variant(double_outer_id, true, R0, R270))
/* OUTER TOP */ /* OUTER TOP */
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, UP_NORTH, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, EAST_UP, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, NORTH_EAST, STAIR_SHAPE, OUTER_LEFT)), GBlockstate.when(FACING, NORTH_EAST, SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R0)) GBlockstate.variant(double_outer_id, true, R180, R0))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, SOUTH_UP, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, EAST_UP, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, EAST_UP, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, EAST_SOUTH, STAIR_SHAPE, OUTER_LEFT)), GBlockstate.when(FACING, EAST_SOUTH, SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R90)) GBlockstate.variant(double_outer_id, true, R180, R90))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, SOUTH_UP, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, SOUTH_UP, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, OUTER_RIGHT), GBlockstate.when(FACING, UP_WEST, SHAPE, OUTER_RIGHT),
GBlockstate.when(CORNER, SOUTH_WEST, STAIR_SHAPE, OUTER_LEFT)), GBlockstate.when(FACING, SOUTH_WEST, SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R180)) GBlockstate.variant(double_outer_id, true, R180, R180))
.with(When.anyOf( .with(When.anyOf(
GBlockstate.when(CORNER, UP_NORTH, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, UP_NORTH, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, UP_WEST, STAIR_SHAPE, OUTER_LEFT), GBlockstate.when(FACING, UP_WEST, SHAPE, OUTER_LEFT),
GBlockstate.when(CORNER, WEST_NORTH, STAIR_SHAPE, OUTER_LEFT)), GBlockstate.when(FACING, WEST_NORTH, SHAPE, OUTER_LEFT)),
GBlockstate.variant(double_outer_id, true, R180, R270)); GBlockstate.variant(double_outer_id, true, R180, R270));
} }
@Override
public void setRecipe(RecipeExporter exporter) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, this, 4)
.pattern("I ")
.pattern("II ")
.pattern("III")
.input('I', ReFramed.CUBE)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
.offerTo(exporter);
}
static { static {
final VoxelShape STRAIGHT = Stream.of( final VoxelShape STRAIGHT = Stream.of(
VoxelShapes.cuboid(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f), VoxelShapes.cuboid(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f),

View File

@ -1,136 +0,0 @@
package fr.adrien1106.reframed.block;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.generator.GBlockstate;
import fr.adrien1106.reframed.generator.BlockStateProvider;
import fr.adrien1106.reframed.util.BlockHelper;
import fr.adrien1106.reframed.util.VoxelHelper;
import fr.adrien1106.reframed.util.property.Corner;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.state.StateManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static fr.adrien1106.reframed.util.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.property.Corner.*;
import static net.minecraft.data.client.VariantSettings.Rotation.*;
public class ReFramedStepBlock extends WaterloggableReFramedBlock implements BlockStateProvider {
public static final List<VoxelShape> STEP_VOXELS = new ArrayList<>(12);
public ReFramedStepBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(CORNER, Corner.NORTH_DOWN));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(CORNER));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return super.getPlacementState(ctx).with(CORNER, BlockHelper.getPlacementCorner(ctx));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return switch (state.get(CORNER)) {
case DOWN_SOUTH -> STEP_VOXELS.get(0);
case NORTH_DOWN -> STEP_VOXELS.get(1);
case UP_NORTH -> STEP_VOXELS.get(2);
case SOUTH_UP -> STEP_VOXELS.get(3);
case DOWN_EAST -> STEP_VOXELS.get(4);
case WEST_DOWN -> STEP_VOXELS.get(5);
case UP_WEST -> STEP_VOXELS.get(6);
case EAST_UP -> STEP_VOXELS.get(7);
case NORTH_EAST -> STEP_VOXELS.get(8);
case EAST_SOUTH -> STEP_VOXELS.get(9);
case SOUTH_WEST -> STEP_VOXELS.get(10);
case WEST_NORTH -> STEP_VOXELS.get(11);
};
}
@Override
public MultipartBlockStateSupplier getMultipart() {
Identifier step_id = ReFramed.id("step_special");
return MultipartBlockStateSupplier.create(this)
/* X AXIS */
.with(GBlockstate.when(CORNER, DOWN_EAST),
GBlockstate.variant(step_id, true, R0, R0))
.with(GBlockstate.when(CORNER, EAST_UP),
GBlockstate.variant(step_id, true, R180, R0))
.with(GBlockstate.when(CORNER, UP_WEST),
GBlockstate.variant(step_id, true, R180, R180))
.with(GBlockstate.when(CORNER, WEST_DOWN),
GBlockstate.variant(step_id, true, R0, R180))
/* Y AXIS */
.with(GBlockstate.when(CORNER, EAST_SOUTH),
GBlockstate.variant(step_id, true, R90, R0))
.with(GBlockstate.when(CORNER, SOUTH_WEST),
GBlockstate.variant(step_id, true, R90, R90))
.with(GBlockstate.when(CORNER, WEST_NORTH),
GBlockstate.variant(step_id, true, R90, R180))
.with(GBlockstate.when(CORNER, NORTH_EAST),
GBlockstate.variant(step_id, true, R90, R270))
/* Z AXIS */
.with(GBlockstate.when(CORNER, DOWN_SOUTH),
GBlockstate.variant(step_id, true, R0, R90))
.with(GBlockstate.when(CORNER, NORTH_DOWN),
GBlockstate.variant(step_id, true, R0, R270))
.with(GBlockstate.when(CORNER, UP_NORTH),
GBlockstate.variant(step_id, true, R180, R270))
.with(GBlockstate.when(CORNER, SOUTH_UP),
GBlockstate.variant(step_id, true, R180, R90));
}
@Override
public void setRecipe(RecipeExporter exporter) {
RecipeProvider.offerStonecuttingRecipe(exporter, RecipeCategory.BUILDING_BLOCKS, this, ReFramed.CUBE, 4);
ShapedRecipeJsonBuilder
.create(RecipeCategory.BUILDING_BLOCKS, this, 8)
.pattern("II")
.input('I', ReFramed.CUBE)
.criterion(FabricRecipeProvider.hasItem(ReFramed.CUBE), FabricRecipeProvider.conditionsFromItem(ReFramed.CUBE))
.criterion(FabricRecipeProvider.hasItem(this), FabricRecipeProvider.conditionsFromItem(this))
.offerTo(exporter);
}
static {
final VoxelShape STEP = VoxelShapes.cuboid(0f, 0f, .5f, 1f, .5f, 1f);
STEP_VOXELS.add(STEP);
STEP_VOXELS.add(VoxelHelper.mirror(STEP, Direction.Axis.Z));
STEP_VOXELS.add(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(STEP, Direction.Axis.X), Direction.Axis.Z));
STEP_VOXELS.add(VoxelHelper.rotateCounterClockwise(STEP, Direction.Axis.X));
STEP_VOXELS.add(VoxelHelper.rotateCounterClockwise(STEP, Direction.Axis.Y));
STEP_VOXELS.add(VoxelHelper.mirror(VoxelHelper.rotateCounterClockwise(STEP, Direction.Axis.Y), Direction.Axis.X));
STEP_VOXELS.add(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(STEP, Direction.Axis.Y), Direction.Axis.Z), Direction.Axis.X));
STEP_VOXELS.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateCounterClockwise(STEP, Direction.Axis.Y), Direction.Axis.Z));
STEP_VOXELS.add(VoxelHelper.rotateCounterClockwise(VoxelHelper.rotateClockwise(STEP, Direction.Axis.Z), Direction.Axis.Y));
STEP_VOXELS.add(VoxelHelper.rotateClockwise(STEP, Direction.Axis.Z));
STEP_VOXELS.add(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(STEP, Direction.Axis.Z), Direction.Axis.Y));
STEP_VOXELS.add(VoxelHelper.mirror(VoxelHelper.rotateClockwise(VoxelHelper.rotateClockwise(STEP, Direction.Axis.Z), Direction.Axis.Y), Direction.Axis.Z));
}
}

View File

@ -0,0 +1,94 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import fr.adrien1106.reframed.util.ReframedInteractible;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.TrapdoorBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ReFramedTrapdoorBlock extends TrapdoorBlock implements BlockEntityProvider, ReframedInteractible {
public ReFramedTrapdoorBlock(Settings settings, BlockSetType woodType) {
super(woodType, settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
}
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
super.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), super.getCollisionShape(state, view, pos, ctx));
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
@Override
public boolean canAddRedstoneEmission(BlockState state, BlockView view, BlockPos pos) {
return false;
}
}

View File

@ -0,0 +1,130 @@
package fr.adrien1106.reframed.block;
import com.google.common.base.MoreObjects;
import fr.adrien1106.reframed.ReFramed;
import fr.adrien1106.reframed.util.ReFramedInteractionUtil;
import fr.adrien1106.reframed.mixin.WallBlockAccessor;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.WallBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.enums.WallShape;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class ReFramedWallBlock extends WallBlock implements BlockEntityProvider {
public ReFramedWallBlock(Settings settings) {
super(settings);
setDefaultState(ReFramedInteractionUtil.setDefaultStates(getDefaultState()));
initNewShapemaps(); //WallBlock specific haxx
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(ReFramedInteractionUtil.appendProperties(builder));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
return ReFramedInteractionUtil.modifyPlacementState(super.getPlacementState(ctx), ctx);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ActionResult r = ReFramedInteractionUtil.onUse(state, world, pos, player, hand, hit);
if(!r.isAccepted()) r = super.onUse(state, world, pos, player, hand, hit);
return r;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ReFramedInteractionUtil.onStateReplaced(state, world, pos, newState, moved);
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
ReFramedInteractionUtil.onPlaced(world, pos, state, placer, stack);
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull(ReFramedInteractionUtil.getCollisionShape(state, view, pos, ctx), getNewShape(state, newCollisionShapeMap));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return getNewShape(state, newShapeMap);
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return ReFramedInteractionUtil.emitsRedstonePower(state);
}
@Override
public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getWeakRedstonePower(state, view, pos, dir);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return ReFramedInteractionUtil.getStrongRedstonePower(state, view, pos, dir);
}
//Shapemap heck (WallBlock has a map keyed on BlockState, but since we add more blockstates most of those map lookups fail)
protected record ShapeKey(boolean up, WallShape north, WallShape east, WallShape south, WallShape west) {
static ShapeKey fromBlockstate(BlockState state) {
return new ShapeKey(
state.get(WallBlock.UP),
state.get(WallBlock.NORTH_SHAPE),
state.get(WallBlock.EAST_SHAPE),
state.get(WallBlock.SOUTH_SHAPE),
state.get(WallBlock.WEST_SHAPE)
);
}
}
protected final Map<ShapeKey, VoxelShape> newShapeMap = new HashMap<>();
protected final Map<ShapeKey, VoxelShape> newCollisionShapeMap = new HashMap<>();
protected void initNewShapemaps() {
initNewShapemap(((WallBlockAccessor) this).getShapeMap(), newShapeMap);
initNewShapemap(((WallBlockAccessor) this).getCollisionShapeMap(), newCollisionShapeMap);
}
protected void initNewShapemap(Map<BlockState, VoxelShape> oldShapeMap, Map<ShapeKey, VoxelShape> newShapeMap) {
oldShapeMap.forEach((state, shape) -> newShapeMap.putIfAbsent(ShapeKey.fromBlockstate(state), shape));
}
protected VoxelShape getNewShape(BlockState state, Map<ShapeKey, VoxelShape> shapes) {
return shapes.getOrDefault(ShapeKey.fromBlockstate(state), VoxelShapes.empty());
}
}

View File

@ -1,43 +0,0 @@
package fr.adrien1106.reframed.block;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Waterloggable;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.Nullable;
public class WaterloggableReFramedDoubleBlock extends ReFramedDoubleBlock implements Waterloggable {
public WaterloggableReFramedDoubleBlock(Settings settings) {
super(settings);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(Properties.WATERLOGGED));
}
@Nullable
@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
BlockState sup = super.getPlacementState(ctx);
if(sup != null) sup = sup.with(Properties.WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).isOf(Fluids.WATER));
return sup;
}
@Override
public FluidState getFluidState(BlockState state) {
return state.get(Properties.WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state);
}
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState otherState, WorldAccess world, BlockPos pos, BlockPos moved) {
if(state.get(Properties.WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
return super.getStateForNeighborUpdate(state, direction, otherState, world, pos, moved);
}
}

View File

@ -26,7 +26,32 @@ public class ReFramedClient implements ClientModInitializer {
//all frames mustn't be on the SOLID layer because they are not opaque! //all frames mustn't be on the SOLID layer because they are not opaque!
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ReFramed.BLOCKS.toArray(new Block[0])); BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ReFramed.BLOCKS.toArray(new Block[0]));
HELPER.addReFramedModel("button_special" , HELPER.auto(new Identifier("block/button")));
HELPER.addReFramedModel("button_pressed_special" , HELPER.auto(new Identifier("block/button_pressed")));
HELPER.addReFramedModel("one_candle_special" , HELPER.auto(new Identifier("block/template_candle")));
HELPER.addReFramedModel("two_candles_special" , HELPER.auto(new Identifier("block/template_two_candles")));
HELPER.addReFramedModel("three_candles_special" , HELPER.auto(new Identifier("block/template_three_candles")));
HELPER.addReFramedModel("four_candles_special" , HELPER.auto(new Identifier("block/template_four_candles")));
HELPER.addReFramedModel("carpet_special" , HELPER.auto(new Identifier("block/carpet")));
HELPER.addReFramedModel("cube_special" , HELPER.auto(new Identifier("block/cube"))); HELPER.addReFramedModel("cube_special" , HELPER.auto(new Identifier("block/cube")));
HELPER.addReFramedModel("door_bottom_left_special" , HELPER.auto(new Identifier("block/door_bottom_left")));
HELPER.addReFramedModel("door_bottom_right_special" , HELPER.auto(new Identifier("block/door_bottom_right")));
HELPER.addReFramedModel("door_top_left_special" , HELPER.auto(new Identifier("block/door_top_left")));
HELPER.addReFramedModel("door_top_right_special" , HELPER.auto(new Identifier("block/door_top_right")));
HELPER.addReFramedModel("door_bottom_left_open_special" , HELPER.auto(new Identifier("block/door_bottom_left_open")));
HELPER.addReFramedModel("door_bottom_right_open_special" , HELPER.auto(new Identifier("block/door_bottom_right_open"))); //This is why we dont format code as tables kids
HELPER.addReFramedModel("door_top_left_open_special" , HELPER.auto(new Identifier("block/door_top_left_open")));
HELPER.addReFramedModel("door_top_right_open_special" , HELPER.auto(new Identifier("block/door_top_right_open")));
HELPER.addReFramedModel("fence_post_special" , HELPER.auto(new Identifier("block/fence_post")));
HELPER.addReFramedModel("fence_gate_special" , HELPER.auto(new Identifier("block/template_fence_gate")));
HELPER.addReFramedModel("fence_gate_open_special" , HELPER.auto(new Identifier("block/template_fence_gate_open")));
HELPER.addReFramedModel("fence_gate_wall_special" , HELPER.auto(new Identifier("block/template_fence_gate_wall")));
HELPER.addReFramedModel("fence_gate_wall_open_special" , HELPER.auto(new Identifier("block/template_fence_gate_wall_open")));
HELPER.addReFramedModel("glass_pane_post_special" , HELPER.auto(new Identifier("block/glass_pane_post")));
HELPER.addReFramedModel("glass_pane_noside_special" , HELPER.auto(new Identifier("block/glass_pane_noside")));
HELPER.addReFramedModel("glass_pane_noside_alt_special" , HELPER.auto(new Identifier("block/glass_pane_noside_alt")));
HELPER.addReFramedModel("pressure_plate_up_special" , HELPER.auto(new Identifier("block/pressure_plate_up")));
HELPER.addReFramedModel("pressure_plate_down_special" , HELPER.auto(new Identifier("block/pressure_plate_down")));
HELPER.addReFramedModel("slab_special" , HELPER.auto(new Identifier("block/slab"))); HELPER.addReFramedModel("slab_special" , HELPER.auto(new Identifier("block/slab")));
HELPER.addReFramedModel("double_slab_special" , HELPER.autoDouble(new Identifier("block/slab"), new Identifier("block/slab_top"))); HELPER.addReFramedModel("double_slab_special" , HELPER.autoDouble(new Identifier("block/slab"), new Identifier("block/slab_top")));
HELPER.addReFramedModel("stairs_special" , HELPER.auto(ReFramed.id("block/stairs"))); HELPER.addReFramedModel("stairs_special" , HELPER.auto(ReFramed.id("block/stairs")));
@ -39,18 +64,42 @@ public class ReFramedClient implements ClientModInitializer {
HELPER.addReFramedModel("double_inner_stairs_special" , HELPER.autoDouble(ReFramed.id("block/inner_stairs"), ReFramed.id("block/inner_stairs_complement"))); HELPER.addReFramedModel("double_inner_stairs_special" , HELPER.autoDouble(ReFramed.id("block/inner_stairs"), ReFramed.id("block/inner_stairs_complement")));
HELPER.addReFramedModel("double_outer_stairs_special" , HELPER.autoDouble(ReFramed.id("block/outer_stairs"), ReFramed.id("block/outer_stairs_complement"))); HELPER.addReFramedModel("double_outer_stairs_special" , HELPER.autoDouble(ReFramed.id("block/outer_stairs"), ReFramed.id("block/outer_stairs_complement")));
HELPER.addReFramedModel("double_outer_side_stairs_special", HELPER.autoDouble(ReFramed.id("block/outer_side_stairs"), ReFramed.id("block/outer_side_stairs_complement"))); HELPER.addReFramedModel("double_outer_side_stairs_special", HELPER.autoDouble(ReFramed.id("block/outer_side_stairs"), ReFramed.id("block/outer_side_stairs_complement")));
HELPER.addReFramedModel("step_special" , HELPER.auto(ReFramed.id("block/step"))); HELPER.addReFramedModel("trapdoor_bottom_special" , HELPER.auto(new Identifier("block/template_trapdoor_bottom")));
HELPER.addReFramedModel("double_step_special" , HELPER.autoDouble(ReFramed.id("block/step"), ReFramed.id("block/step_complement_slab"))); HELPER.addReFramedModel("trapdoor_top_special" , HELPER.auto(new Identifier("block/template_trapdoor_top")));
HELPER.addReFramedModel("double_step_side_special" , HELPER.autoDouble(ReFramed.id("block/step_side"), ReFramed.id("block/step_side_complement_slab"))); HELPER.addReFramedModel("wall_post_special" , HELPER.auto(new Identifier("block/template_wall_post")));
//vanilla style models (using "special-sprite replacement" method)
HELPER.addReFramedModel("lever_special" , HELPER.json(ReFramed.id("block/lever")));
HELPER.addReFramedModel("trapdoor_open_special" , HELPER.json(ReFramed.id("block/trapdoor_open")));
HELPER.addReFramedModel("lever_on_special" , HELPER.json(ReFramed.id("block/lever_on")));
//these next five only exist because AutoRetexturedModels don't seem to rotate their textures the right way when rotated from a multipart blockstate
HELPER.addReFramedModel("fence_side_special" , HELPER.json(ReFramed.id("block/fence_side")));
HELPER.addReFramedModel("glass_pane_side_special" , HELPER.json(ReFramed.id("block/glass_pane_side")));
HELPER.addReFramedModel("glass_pane_side_alt_special" , HELPER.json(ReFramed.id("block/glass_pane_side_alt")));
HELPER.addReFramedModel("wall_side_special" , HELPER.json(ReFramed.id("block/wall_side")));
HELPER.addReFramedModel("wall_side_tall_special" , HELPER.json(ReFramed.id("block/wall_side_tall")));
//item only models
HELPER.addReFramedModel("button_inventory_special" , HELPER.auto(new Identifier("block/button_inventory")));
HELPER.addReFramedModel("fence_inventory_special" , HELPER.auto(new Identifier("block/fence_inventory")));
HELPER.addReFramedModel("fence_post_inventory_special" , HELPER.auto(ReFramed.id("block/fence_post_inventory")));
HELPER.addReFramedModel("wall_inventory_special" , HELPER.auto(new Identifier("block/wall_inventory")));
//item model assignments (in lieu of models/item/___.json) //item model assignments (in lieu of models/item/___.json)
HELPER.assignItemModel("button_inventory_special" , ReFramed.BUTTON);
HELPER.assignItemModel("carpet_special" , ReFramed.CARPET);
HELPER.assignItemModel("cube_special" , ReFramed.CUBE); HELPER.assignItemModel("cube_special" , ReFramed.CUBE);
HELPER.assignItemModel("fence_inventory_special" , ReFramed.FENCE);
HELPER.assignItemModel("fence_gate_special" , ReFramed.FENCE_GATE);
HELPER.assignItemModel("trapdoor_bottom_special" , ReFramed.IRON_TRAPDOOR);
HELPER.assignItemModel("fence_post_inventory_special" , ReFramed.POST);
HELPER.assignItemModel("pressure_plate_up_special" , ReFramed.PRESSURE_PLATE);
HELPER.assignItemModel("slab_special" , ReFramed.SLAB); HELPER.assignItemModel("slab_special" , ReFramed.SLAB);
HELPER.assignItemModel("double_slab_special" , ReFramed.DOUBLE_SLAB); HELPER.assignItemModel("double_slab_special" , ReFramed.DOUBLE_SLAB);
HELPER.assignItemModel("stairs_special" , ReFramed.STAIRS); HELPER.assignItemModel("stairs_special" , ReFramed.STAIRS);
HELPER.assignItemModel("double_stairs_special" , ReFramed.DOUBLE_STAIRS); HELPER.assignItemModel("double_stairs_special" , ReFramed.DOUBLE_STAIRS);
HELPER.assignItemModel("step_special" , ReFramed.STEP); HELPER.assignItemModel("trapdoor_bottom_special" , ReFramed.TRAPDOOR);
HELPER.assignItemModel("double_step_special" , ReFramed.DOUBLE_STEP); HELPER.assignItemModel("wall_inventory_special" , ReFramed.WALL);
} }
private void privateInit() { private void privateInit() {

View File

@ -1,7 +0,0 @@
package fr.adrien1106.reframed.generator;
import net.minecraft.data.client.BlockStateSupplier;
public interface BlockStateProvider {
BlockStateSupplier getMultipart();
}

View File

@ -1,44 +0,0 @@
package fr.adrien1106.reframed.generator;
import fr.adrien1106.reframed.ReFramed;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricAdvancementProvider;
import net.minecraft.advancement.Advancement;
import net.minecraft.advancement.AdvancementEntry;
import net.minecraft.advancement.AdvancementFrame;
import net.minecraft.advancement.AdvancementRewards;
import net.minecraft.advancement.criterion.InventoryChangedCriterion;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.function.Consumer;
public class GAdvancement extends FabricAdvancementProvider {
protected GAdvancement(FabricDataOutput output) {
super(output);
}
@Override
public void generateAdvancement(Consumer<AdvancementEntry> consumer) {
Advancement.Builder builder = Advancement.Builder.create()
.display(
Items.CAKE,
Text.literal("Is Everything A Lie ?"),
Text.translatable("advancements.reframed.description"),
new Identifier("textures/gui/advancements/backgrounds/adventure.png"),
AdvancementFrame.TASK,
true,
true,
false
).rewards(AdvancementRewards.Builder.experience(1000));
ReFramed.BLOCKS.forEach(block ->
builder.criterion(
"get_" + Registries.BLOCK.getId(block).getPath(),
InventoryChangedCriterion.Conditions.items(block)
)
);
builder.build(consumer, ReFramed.MODID + "/root");
}
}

View File

@ -1,6 +1,5 @@
package fr.adrien1106.reframed.generator; package fr.adrien1106.reframed.generator;
import fr.adrien1106.reframed.ReFramed;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
@ -13,6 +12,6 @@ public class GBlockLoot extends FabricBlockLootTableProvider {
@Override @Override
public void generate() { public void generate() {
ReFramed.BLOCKS.forEach(block -> addDrop(block, Registries.ITEM.get(Registries.BLOCK.getId(block)))); Generator.BLOCKS.forEach(block -> addDrop(block, Registries.ITEM.get(Registries.BLOCK.getId(block))));
} }
} }

View File

@ -1,22 +0,0 @@
package fr.adrien1106.reframed.generator;
import fr.adrien1106.reframed.ReFramed;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider.BlockTagProvider;
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
import net.minecraft.registry.tag.BlockTags;
import java.util.concurrent.CompletableFuture;
public class GBlockTag extends BlockTagProvider {
public GBlockTag(FabricDataOutput output, CompletableFuture<WrapperLookup> registries) {
super(output, registries);
}
@Override
protected void configure(WrapperLookup arg) {
FabricTagBuilder builder = getOrCreateTagBuilder(BlockTags.AXE_MINEABLE);
ReFramed.BLOCKS.forEach(builder::add);
}
}

View File

@ -1,6 +1,5 @@
package fr.adrien1106.reframed.generator; package fr.adrien1106.reframed.generator;
import fr.adrien1106.reframed.ReFramed;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
import net.minecraft.data.client.*; import net.minecraft.data.client.*;
@ -9,8 +8,6 @@ import net.minecraft.util.Identifier;
import java.util.Objects; import java.util.Objects;
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
public class GBlockstate extends FabricModelProvider { public class GBlockstate extends FabricModelProvider {
public GBlockstate(FabricDataOutput output) { public GBlockstate(FabricDataOutput output) {
@ -19,20 +16,10 @@ public class GBlockstate extends FabricModelProvider {
@Override @Override
public void generateBlockStateModels(BlockStateModelGenerator model_generator) { public void generateBlockStateModels(BlockStateModelGenerator model_generator) {
ReFramed.BLOCKS Generator.BLOCKS
.forEach(model_generator::excludeFromSimpleItemModelGeneration); .forEach(model_generator::excludeFromSimpleItemModelGeneration);
ReFramed.BLOCKS.stream() Generator.BLOCKS.stream()
.map(block -> { .map(block -> block instanceof MultipartBlockStateProvider multipart_block ? multipart_block.getMultipart(): null)
if (block instanceof BlockStateProvider multipart_block) return multipart_block.getMultipart();
return VariantsBlockStateSupplier.create(
block,
GBlockstate.variant(
ReFramed.id("cube_special"),
true,
R0, R0
)
);
})
.filter(Objects::nonNull) .filter(Objects::nonNull)
.forEach(model_generator.blockStateCollector); .forEach(model_generator.blockStateCollector);
} }
@ -43,8 +30,8 @@ public class GBlockstate extends FabricModelProvider {
public static BlockStateVariant variant(Identifier model, boolean uv_lock, VariantSettings.Rotation x, VariantSettings.Rotation y) { public static BlockStateVariant variant(Identifier model, boolean uv_lock, VariantSettings.Rotation x, VariantSettings.Rotation y) {
BlockStateVariant variant = BlockStateVariant.create().put(VariantSettings.MODEL, model); BlockStateVariant variant = BlockStateVariant.create().put(VariantSettings.MODEL, model);
if (uv_lock) variant.put(VariantSettings.UVLOCK, uv_lock); if (uv_lock) variant.put(VariantSettings.UVLOCK, uv_lock);
if (!x.equals(R0)) variant.put(VariantSettings.X, x); if (!x.equals(VariantSettings.Rotation.R0)) variant.put(VariantSettings.X, x);
if (!y.equals(R0)) variant.put(VariantSettings.Y, y); if (!y.equals(VariantSettings.Rotation.R0)) variant.put(VariantSettings.Y, y);
return variant; return variant;
} }

View File

@ -1,30 +0,0 @@
package fr.adrien1106.reframed.generator;
import fr.adrien1106.reframed.ReFramed;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider;
import net.minecraft.registry.Registries;
import java.util.Arrays;
import java.util.stream.Collectors;
public class GLanguage extends FabricLanguageProvider {
protected GLanguage(FabricDataOutput dataOutput) {
super(dataOutput, "en_us");
}
@Override
public void generateTranslations(TranslationBuilder builder) {
builder.add(Registries.ITEM_GROUP.getKey(ReFramed.ITEM_GROUP).get(), "Frames");
builder.add("advancements.reframed.description", "Get all the frame types.");
ReFramed.BLOCKS.forEach(block -> {
builder.add(block, beautify(Registries.BLOCK.getId(block).getPath()) + " Frame");
});
}
private static String beautify(String name) {
return Arrays.stream(name.split("_"))
.map(word -> word.substring(0, 1).toUpperCase() + word.substring(1))
.collect(Collectors.joining(" "));
}
}

View File

@ -1,19 +0,0 @@
package fr.adrien1106.reframed.generator;
import fr.adrien1106.reframed.ReFramed;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.data.server.recipe.RecipeExporter;
public class GRecipe extends FabricRecipeProvider {
public GRecipe(FabricDataOutput output) {
super(output);
}
@Override
public void generate(RecipeExporter exporter) {
ReFramed.BLOCKS.forEach(block -> {
if (block instanceof RecipeSetter provider) provider.setRecipe(exporter);
});
}
}

View File

@ -2,17 +2,22 @@ package fr.adrien1106.reframed.generator;
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.minecraft.block.Block;
import java.util.List;
import static fr.adrien1106.reframed.ReFramed.*;
public class Generator implements DataGeneratorEntrypoint { public class Generator implements DataGeneratorEntrypoint {
/**
* missing DOOR, IRON_DOOR, CANDLE
*/
public static List<Block> BLOCKS = List.of(CUBE, STAIRS, DOUBLE_STAIRS, SLAB, DOUBLE_SLAB, POST, FENCE, FENCE_GATE, TRAPDOOR, IRON_TRAPDOOR, PRESSURE_PLATE, BUTTON, LEVER, WALL, CARPET, PANE);
@Override @Override
public void onInitializeDataGenerator(FabricDataGenerator data_generator) { public void onInitializeDataGenerator(FabricDataGenerator data_generator) {
FabricDataGenerator.Pack my_pack = data_generator.createPack(); FabricDataGenerator.Pack myPack = data_generator.createPack();
my_pack.addProvider(GBlockLoot::new); myPack.addProvider(GBlockLoot::new);
my_pack.addProvider(GBlockstate::new); myPack.addProvider(GBlockstate::new);
my_pack.addProvider(GLanguage::new);
my_pack.addProvider(GBlockTag::new);
my_pack.addProvider(GRecipe::new);
my_pack.addProvider(GAdvancement::new);
} }
} }

View File

@ -0,0 +1,7 @@
package fr.adrien1106.reframed.generator;
import net.minecraft.data.client.MultipartBlockStateSupplier;
public interface MultipartBlockStateProvider {
MultipartBlockStateSupplier getMultipart();
}

View File

@ -1,8 +0,0 @@
package fr.adrien1106.reframed.generator;
import net.minecraft.data.server.recipe.RecipeExporter;
public interface RecipeSetter {
void setRecipe(RecipeExporter exporter);
}

View File

@ -1,6 +1,6 @@
package fr.adrien1106.reframed.mixin.compat; package fr.adrien1106.reframed.mixin.compat;
import fr.adrien1106.reframed.util.BlockHelper; import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.util.IBlockRenderInfoMixin; import fr.adrien1106.reframed.util.IBlockRenderInfoMixin;
import fr.adrien1106.reframed.util.ThemeableBlockEntity; import fr.adrien1106.reframed.util.ThemeableBlockEntity;
import link.infra.indium.renderer.render.BlockRenderInfo; import link.infra.indium.renderer.render.BlockRenderInfo;
@ -32,7 +32,7 @@ public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity
|| view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) || view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity))
return instance.shouldDrawSide(state, view, pos, face); return instance.shouldDrawSide(state, view, pos, face);
return BlockHelper.shouldDrawSide(state, view, pos, face, other_pos, theme_index); return ReFramedBlock.shouldDrawSide(state, view, pos, face, other_pos, theme_index);
} }
@Override @Override

View File

@ -1,7 +1,7 @@
package fr.adrien1106.reframed.mixin.compat; package fr.adrien1106.reframed.mixin.compat;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import fr.adrien1106.reframed.util.BlockHelper; import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.util.ThemeableBlockEntity; import fr.adrien1106.reframed.util.ThemeableBlockEntity;
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache; import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -25,6 +25,6 @@ public class SodiumBlockOcclusionCacheMixin {
), cancellable = true) ), cancellable = true)
private void shouldDrawFrameNeighborSide(BlockState self_state, BlockView view, BlockPos self_pos, Direction face, CallbackInfoReturnable<Boolean> cir, @Local BlockPos.Mutable other_pos) { private void shouldDrawFrameNeighborSide(BlockState self_state, BlockView view, BlockPos self_pos, Direction face, CallbackInfoReturnable<Boolean> cir, @Local BlockPos.Mutable other_pos) {
if (!(view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return; if (!(view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return;
cir.setReturnValue(BlockHelper.shouldDrawSide(self_state, view, self_pos, face, other_pos, 0)); cir.setReturnValue(ReFramedBlock.shouldDrawSide(self_state, view, self_pos, face, other_pos, 0));
} }
} }

View File

@ -1,7 +1,7 @@
package fr.adrien1106.reframed.mixin.render; package fr.adrien1106.reframed.mixin.render;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import fr.adrien1106.reframed.util.BlockHelper; import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.util.IBlockRenderInfoMixin; import fr.adrien1106.reframed.util.IBlockRenderInfoMixin;
import fr.adrien1106.reframed.util.ThemeableBlockEntity; import fr.adrien1106.reframed.util.ThemeableBlockEntity;
import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo; import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo;
@ -38,7 +38,7 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
@Redirect(method = "shouldDrawFace", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/BlockPos;)Z")) @Redirect(method = "shouldDrawFace", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/BlockPos;)Z"))
private boolean shouldDrawAdjacentCamoSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos) { private boolean shouldDrawAdjacentCamoSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos) {
return BlockHelper.shouldDrawSide(state, world, pos, side, other_pos, theme_index); return ReFramedBlock.shouldDrawSide(state, world, pos, side, other_pos, theme_index);
} }
@Override @Override

View File

@ -19,7 +19,7 @@ public class LivingEntityMixin {
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/world/World;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;" target = "Lnet/minecraft/world/World;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;"
) ), remap = false
) )
private BlockState playCamoFallSound(World world, BlockPos pos) { private BlockState playCamoFallSound(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);

View File

@ -1,305 +0,0 @@
package fr.adrien1106.reframed.util;
import fr.adrien1106.reframed.block.ReFramedBlock;
import fr.adrien1106.reframed.block.ReFramedEntity;
import fr.adrien1106.reframed.util.property.Corner;
import fr.adrien1106.reframed.util.property.StairShape;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static fr.adrien1106.reframed.util.BlockProperties.CORNER;
import static fr.adrien1106.reframed.util.BlockProperties.LIGHT;
import static fr.adrien1106.reframed.util.property.StairShape.*;
import static net.minecraft.util.shape.VoxelShapes.combine;
public class BlockHelper {
public static Corner getPlacementCorner(ItemPlacementContext ctx) {
Direction side = ctx.getSide().getOpposite();
Vec3d pos = getHitPos(ctx.getHitPos(), ctx.getBlockPos());
Direction.Axis axis = getHitAxis(pos, side);
Direction part_direction = Direction.from(
axis,
axis.choose(pos.x, pos.y, pos.z) > 0
? Direction.AxisDirection.POSITIVE
: Direction.AxisDirection.NEGATIVE
);
return Corner.getByDirections(side, part_direction);
}
public static Direction.Axis getHitAxis(Vec3d pos, Direction side) {
Stream<Direction.Axis> axes = Stream.of(Direction.Axis.values()).filter(axis -> !axis.equals(side.getAxis()));
return axes.reduce((axis_1, axis_2) ->
Math.abs(axis_1.choose(pos.x, pos.y, pos.z)) > Math.abs(axis_2.choose(pos.x, pos.y, pos.z))
? axis_1
: axis_2
).get();
}
public static Vec3d getRelativePos(Vec3d pos, BlockPos block_pos) {
return new Vec3d(
pos.getX() - block_pos.getX(),
pos.getY() - block_pos.getY(),
pos.getZ() - block_pos.getZ()
);
}
public static Vec3d getHitPos(Vec3d pos, BlockPos block_pos) {
pos = getRelativePos(pos, block_pos);
return new Vec3d(
pos.getX() - .5d,
pos.getY() - .5d,
pos.getZ() - .5d
);
}
public static StairShape getStairsShape(Block block, Corner face, BlockView world, BlockPos pos) {
StairShape shape = STRAIGHT;
String sol = getNeighborPos(face, face.getFirstDirection(), true, face.getSecondDirection(), world, pos, block);
switch (sol) {
case "right": return INNER_RIGHT;
case "left": return INNER_LEFT;
}
sol = getNeighborPos(face, face.getSecondDirection(), true, face.getFirstDirection(), world, pos, block);
switch (sol) {
case "right": return INNER_RIGHT;
case "left": return INNER_LEFT;
}
sol = getNeighborPos(face, face.getFirstDirection(), false, face.getSecondDirection(), world, pos, block);
switch (sol) {
case "right" -> shape = FIRST_OUTER_RIGHT;
case "left" -> shape = FIRST_OUTER_LEFT;
}
sol = getNeighborPos(face, face.getSecondDirection(), false, face.getFirstDirection(), world, pos, block);
switch (sol) {
case "right" -> {
if (shape.equals(STRAIGHT)) shape = SECOND_OUTER_RIGHT;
else if (shape.equals(FIRST_OUTER_RIGHT)) shape = OUTER_RIGHT;
}
case "left" -> {
if (shape.equals(STRAIGHT)) shape = SECOND_OUTER_LEFT;
else if (shape.equals(FIRST_OUTER_LEFT)) shape = OUTER_LEFT;
}
}
return shape;
}
public static String getNeighborPos(Corner face, Direction direction, Boolean reverse, Direction reference, BlockView world, BlockPos pos, Block block) {
BlockState block_state = world.getBlockState(
pos.offset(reverse ? direction.getOpposite() : direction)
);
if (block_state.isOf(block) && block_state.get(CORNER).hasDirection(reference)) {
if (block_state.get(CORNER).hasDirection(face.getLeftDirection())) return "left";
else if (block_state.get(CORNER).hasDirection(face.getRightDirection())) return "right";
}
return "";
}
public static ActionResult useCamo(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, int theme_index) {
if(!(world.getBlockEntity(pos) instanceof ReFramedEntity block_entity)) return ActionResult.PASS;
// Changing the theme
ItemStack held = player.getStackInHand(hand);
if(held.getItem() instanceof BlockItem block_item && block_entity.getTheme(theme_index).getBlock() == Blocks.AIR) {
Block block = block_item.getBlock();
ItemPlacementContext ctx = new ItemPlacementContext(new ItemUsageContext(player, hand, hit));
BlockState placement_state = block.getPlacementState(ctx);
if(placement_state != null && Block.isShapeFullCube(placement_state.getCollisionShape(world, pos)) && !(block instanceof BlockEntityProvider)) {
List<BlockState> themes = block_entity.getThemes();
if(!world.isClient) block_entity.setTheme(placement_state, theme_index);
// check for default light emission
if (placement_state.getLuminance() > 0
&& themes.stream().noneMatch(theme -> theme.getLuminance() > 0))
if (block_entity.emitsLight()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
else block_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
// check for default redstone emission
if (placement_state.getWeakRedstonePower(world, pos, Direction.NORTH) > 0
&& themes.stream().noneMatch(theme -> theme.getWeakRedstonePower(world, pos, Direction.NORTH) > 0))
if (block_entity.emitsRedstone()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
else block_entity.toggleRedstone();
if(!player.isCreative()) held.decrement(1);
world.playSound(player, pos, placement_state.getSoundGroup().getPlaceSound(), SoundCategory.BLOCKS, 1f, 1.1f);
return ActionResult.SUCCESS;
}
}
return ActionResult.PASS;
}
public static ActionResult useUpgrade(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand) {
if(!(world.getBlockEntity(pos) instanceof ReFramedEntity block_entity)) return ActionResult.PASS;
ItemStack held = player.getStackInHand(hand);
ReframedInteractible ext = state.getBlock() instanceof ReframedInteractible e ? e : ReframedInteractible.Default.INSTANCE;
// frame will emit light if applied with glowstone
if(state.contains(LIGHT) && held.getItem() == Items.GLOWSTONE_DUST) {
block_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
if(!player.isCreative())
if (block_entity.emitsLight()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.BLOCK_GLASS_HIT, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// frame will emit redstone if applied with redstone torch can deactivate redstone block camo emission
if(held.getItem() == Items.REDSTONE_TORCH && ext.canAddRedstoneEmission(state, world, pos)) {
block_entity.toggleRedstone();
if(!player.isCreative())
if (block_entity.emitsRedstone()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// Frame will lose its collision if applied with popped chorus fruit
if(held.getItem() == Items.POPPED_CHORUS_FRUIT && ext.canRemoveCollision(state, world, pos)) {
block_entity.toggleSolidity();
if(!player.isCreative())
if (!block_entity.isSolid()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
// Doing this method from scratch as it is simpler to do than injecting everywhere
public static boolean shouldDrawSide(BlockState self_state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, int theme_index) {
ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e ? e : null;
ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e ? e : null;
BlockState other_state = world.getBlockState(other_pos);
// normal behaviour
if (self == null && other == null) return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
// self is a normal Block
if (self == null && other_state.getBlock() instanceof ReFramedBlock other_block) {
VoxelShape self_shape = self_state.getCullingShape(world, pos);
if (self_shape.isEmpty()) return true;
int i = 0;
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_state.isSideInvisible(s, side) || s.isOpaque())
other_shape = combine(
other_shape,
other_block
.getShape(other_state, i)
.getFace(side.getOpposite()),
BooleanBiFunction.OR
);
}
// determine if side needs to be rendered
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
}
BlockState self_theme = self.getTheme(theme_index);
// other is normal Block
if (other == null && self_state.getBlock() instanceof ReFramedBlock self_block) {
// Transparent is simple if self and the neighbor are invisible don't render side (like default)
if (self_theme.isSideInvisible(other_state, side)) return false;
// Opaque is also simple as each model are rendered one by one
if (other_state.isOpaque()) {
// no cache section :( because it differs between each instance of the frame
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
if (self_shape.isEmpty()) return true;
VoxelShape other_shape = other_state.getCullingFace(world, other_pos, side.getOpposite());
// determine if side needs to be rendered
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
}
return true;
}
// Both are frames
// here both are computed in the same zone as there will necessarily a shape comparison
if (self_state.getBlock() instanceof ReFramedBlock self_block && other_state.getBlock() instanceof ReFramedBlock other_block) {
VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side);
if (self_shape.isEmpty()) return true;
int i = 0;
VoxelShape other_shape = VoxelShapes.empty();
for (BlockState s: other.getThemes()) {
i++;
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
other_shape = combine(
other_shape,
other_block
.getShape(other_state, i)
.getFace(side.getOpposite()),
BooleanBiFunction.OR
);
}
// determine if side needs to be rendered
return VoxelShapes.matchesAnywhere(self_shape, other_shape, BooleanBiFunction.ONLY_FIRST);
}
return true;
}
public static boolean cursorMatchesFace(VoxelShape shape, Vec3d pos) {
Map<Direction.Axis, Double> axes = Arrays.stream(Direction.Axis.values())
.collect(Collectors.toMap(
x -> x,
x -> x.choose(pos.getX(), pos.getY(), pos.getZ())
));
return shape.getBoundingBoxes().stream()
.anyMatch(box ->
axes.keySet().stream()
.map(x -> box.getMin(x) <= axes.get(x) && box.getMax(x) >= axes.get(x))
.reduce((prev, current) -> prev && current).orElse(false)
);
}
public static int luminance(BlockState state) {
return state.contains(LIGHT) && state.get(LIGHT) ? 15 : 0;
}
}

View File

@ -1,12 +0,0 @@
package fr.adrien1106.reframed.util;
import fr.adrien1106.reframed.util.property.Corner;
import fr.adrien1106.reframed.util.property.StairShape;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.EnumProperty;
public class BlockProperties {
public static final BooleanProperty LIGHT = BooleanProperty.of("emits_light");
public static final EnumProperty<Corner> CORNER = EnumProperty.of("corner", Corner.class);
public static final EnumProperty<StairShape> STAIR_SHAPE = EnumProperty.of("shape", StairShape.class);
}

View File

@ -0,0 +1,195 @@
package fr.adrien1106.reframed.util;
import fr.adrien1106.reframed.block.ReFramedEntity;
import net.minecraft.block.*;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
//For an example of how to use this class, have a look at TemplateBlock.
//Basically there are several methods that would like to modify the return value of something.
public class ReFramedInteractionUtil {
@Deprecated // TODO remove
public static final BooleanProperty LIGHT = BooleanProperty.of("frame_light");
@Deprecated // TODO remove
public static StateManager.Builder<Block, BlockState> appendProperties(StateManager.Builder<Block, BlockState> builder) {
return builder.add(LIGHT);
}
//Use this to obtain a Block.Settings that'll make your Template act like the ones in the mod.
//(To complete the look, don't forget to tag your blocks with mineable/axe.)
private static final AbstractBlock.ContextPredicate NOPE = (blah, blahdey, blahh) -> false;
// TODO Find better place
public static AbstractBlock.Settings configureSettings(AbstractBlock.Settings s) {
return s.luminance(ReFramedInteractionUtil::luminance).nonOpaque().sounds(BlockSoundGroup.WOOD).hardness(0.2f).suffocates(NOPE).blockVision(NOPE);
}
// TODO Find better place
//And if you don't have a Block.Settings to copy off of.
public static AbstractBlock.Settings makeSettings() {
return configureSettings(AbstractBlock.Settings.create());
}
@Deprecated // TODO remove
public static BlockState setDefaultStates(BlockState in) {
if(in.contains(LIGHT)) in = in.with(LIGHT, false);
return in;
}
@Deprecated // TODO remove
public static @Nullable BlockState modifyPlacementState(@Nullable BlockState in, ItemPlacementContext ctx) {
return ReFramedEntity.getNbtLightLevel(in, ctx.getStack());
}
@Deprecated // TODO remove
public static ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if(!(world.getBlockEntity(pos) instanceof ReFramedEntity block_entity)) return ActionResult.PASS;
if(!player.canModifyBlocks() || !world.canPlayerModifyAt(player, pos)) return ActionResult.PASS;
ItemStack held = player.getStackInHand(hand);
ReframedInteractible ext = state.getBlock() instanceof ReframedInteractible e ? e : ReframedInteractible.Default.INSTANCE;
// frame will emit light if applied with glowstone
if(state.contains(LIGHT) && held.getItem() == Items.GLOWSTONE_DUST) {
block_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
if(!player.isCreative())
if (block_entity.emitsLight()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.BLOCK_GLASS_HIT, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// frame will emit redstone if applied with redstone torch can deactivate redstone block camo emission
if(held.getItem() == Items.REDSTONE_TORCH && ext.canAddRedstoneEmission(state, world, pos)) {
block_entity.toggleRedstone();
if(!player.isCreative())
if (block_entity.emitsRedstone()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// Frame will lose its collision if applied with popped chorus fruit
if(held.getItem() == Items.POPPED_CHORUS_FRUIT && ext.canRemoveCollision(state, world, pos)) {
block_entity.toggleSolidity();
if(!player.isCreative())
if (!block_entity.isSolid()) held.decrement(1);
else held.increment(1);
world.playSound(player, pos, SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.BLOCKS, 1f, 1f);
return ActionResult.SUCCESS;
}
// Changing the theme
if(held.getItem() instanceof BlockItem block_item && block_entity.getTheme(1).getBlock() == Blocks.AIR) {
Block block = block_item.getBlock();
ItemPlacementContext ctx = new ItemPlacementContext(new ItemUsageContext(player, hand, hit));
BlockState placementState = block.getPlacementState(ctx);
if(placementState != null && Block.isShapeFullCube(placementState.getCollisionShape(world, pos)) && !(block instanceof BlockEntityProvider)) {
// TODO FOR SECOND
if(!world.isClient) block_entity.setTheme(placementState, 1);
// check for default light emission
if (placementState.getLuminance() > 0)
if (block_entity.emitsLight()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
else block_entity.toggleLight();
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
// check for redstone emission
if (placementState.getWeakRedstonePower(world, pos, Direction.NORTH) > 0)
if (block_entity.emitsRedstone()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
else block_entity.toggleRedstone();
if(!player.isCreative()) held.decrement(1);
world.playSound(player, pos, placementState.getSoundGroup().getPlaceSound(), SoundCategory.BLOCKS, 1f, 1.1f);
return ActionResult.SUCCESS;
}
}
return ActionResult.PASS;
}
@Deprecated
public static void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if(!state.isOf(newState.getBlock()) &&
world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity &&
world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)
) {
DefaultedList<ItemStack> drops = DefaultedList.of();
BlockState theme = frame_entity.getTheme(1);
if(theme.getBlock() != Blocks.AIR) drops.add(new ItemStack(theme.getBlock()));
if(frame_entity.emitsRedstone() && theme.getWeakRedstonePower(world, pos, Direction.NORTH) == 0)
drops.add(new ItemStack(Items.REDSTONE_TORCH));
if(frame_entity.emitsLight() && theme.getLuminance() == 0)
drops.add(new ItemStack(Items.GLOWSTONE_DUST));
if(!frame_entity.isSolid() && theme.isSolid())
drops.add(new ItemStack(Items.POPPED_CHORUS_FRUIT));
ItemScatterer.spawn(world, pos, drops);
}
}
@Deprecated
public static void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
//Load the BlockEntityTag clientside, which fixes the template briefly showing its default state when placing it.
//I'm surprised this doesn't happen by default; the BlockEntityTag stuff is only done serverside.
if(world.isClient && world.getBlockEntity(pos) instanceof ReFramedEntity be) {
NbtCompound tag = BlockItem.getBlockEntityNbt(stack);
if(tag != null) be.readNbt(tag);
}
}
@Deprecated
//Returns "null" to signal "no opinion". Imagine it like an InteractionResult.PASS.
public static @Nullable VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return view.getBlockEntity(pos) instanceof ReFramedEntity be && !be.isSolid() ? VoxelShapes.empty() : null;
}
@Deprecated // TODO remove
public static boolean emitsRedstonePower(BlockState state) {
//return state.contains(REDSTONE) ? state.get(REDSTONE) : false;
return false; //TODO, not available after punting this to BlockEntity. Yarn makes this method sound more important than it is, it's just for dust redirection.
}
@Deprecated // TODO remove
public static int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return view.getBlockEntity(pos) instanceof ReFramedEntity be && be.emitsRedstone() ? 15 : 0;
}
@Deprecated // TODO remove
public static int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) {
return view.getBlockEntity(pos) instanceof ReFramedEntity be && be.emitsRedstone() ? 15 : 0;
}
public static int luminance(BlockState state) {
return state.contains(LIGHT) && state.get(LIGHT) ? 15 : 0;
}
}

View File

@ -5,7 +5,7 @@ import net.minecraft.util.math.Direction;
import java.util.Arrays; import java.util.Arrays;
public enum Corner implements StringIdentifiable { public enum StairDirection implements StringIdentifiable {
NORTH_DOWN("north_down", Direction.NORTH, Direction.DOWN, Direction.EAST, 0), NORTH_DOWN("north_down", Direction.NORTH, Direction.DOWN, Direction.EAST, 0),
DOWN_SOUTH("down_south", Direction.DOWN, Direction.SOUTH, Direction.EAST, 1), DOWN_SOUTH("down_south", Direction.DOWN, Direction.SOUTH, Direction.EAST, 1),
SOUTH_UP("south_up", Direction.SOUTH, Direction.UP, Direction.EAST, 2), SOUTH_UP("south_up", Direction.SOUTH, Direction.UP, Direction.EAST, 2),
@ -26,7 +26,7 @@ public enum Corner implements StringIdentifiable {
private final Direction left_direction; private final Direction left_direction;
private final int ID; private final int ID;
Corner(String name, Direction first_direction, Direction second_direction, Direction right_direction, int id) { StairDirection(String name, Direction first_direction, Direction second_direction, Direction right_direction, int id) {
this.name = name; this.name = name;
this.first_direction = first_direction; this.first_direction = first_direction;
this.second_direction = second_direction; this.second_direction = second_direction;
@ -66,21 +66,21 @@ public enum Corner implements StringIdentifiable {
return this.ID; return this.ID;
} }
public static Corner getByDirections(Direction direction_1, Direction direction_2) { public static StairDirection getByDirections(Direction direction_1, Direction direction_2) {
return Arrays.stream(Corner.values()) return Arrays.stream(StairDirection.values())
.filter(value -> value.hasDirection(direction_1) && value.hasDirection(direction_2)) .filter(value -> value.hasDirection(direction_1) && value.hasDirection(direction_2))
.findFirst().orElse(Corner.NORTH_DOWN); .findFirst().orElse(StairDirection.NORTH_DOWN);
} }
public static Corner fromId(int id) { public static StairDirection fromId(int id) {
return Arrays.stream(Corner.values()) return Arrays.stream(StairDirection.values())
.filter(value -> value.getID() == id) .filter(value -> value.getID() == id)
.findFirst().orElse(Corner.NORTH_DOWN); .findFirst().orElse(StairDirection.NORTH_DOWN);
} }
public static Corner fromName(String name) { public static StairDirection fromName(String name) {
return Arrays.stream(Corner.values()) return Arrays.stream(StairDirection.values())
.filter(value -> value.name().equals(name)) .filter(value -> value.name().equals(name))
.findFirst().orElse(Corner.NORTH_DOWN); .findFirst().orElse(StairDirection.NORTH_DOWN);
} }
} }

View File

@ -0,0 +1,118 @@
{
"variants": {
"face=ceiling,facing=east,powered=false": {
"model": "reframed:button_special",
"x": 180,
"y": 270
},
"face=ceiling,facing=east,powered=true": {
"model": "reframed:button_pressed_special",
"x": 180,
"y": 270
},
"face=ceiling,facing=north,powered=false": {
"model": "reframed:button_special",
"x": 180,
"y": 180
},
"face=ceiling,facing=north,powered=true": {
"model": "reframed:button_pressed_special",
"x": 180,
"y": 180
},
"face=ceiling,facing=south,powered=false": {
"model": "reframed:button_special",
"x": 180
},
"face=ceiling,facing=south,powered=true": {
"model": "reframed:button_pressed_special",
"x": 180
},
"face=ceiling,facing=west,powered=false": {
"model": "reframed:button_special",
"x": 180,
"y": 90
},
"face=ceiling,facing=west,powered=true": {
"model": "reframed:button_pressed_special",
"x": 180,
"y": 90
},
"face=floor,facing=east,powered=false": {
"model": "reframed:button_special",
"y": 90
},
"face=floor,facing=east,powered=true": {
"model": "reframed:button_pressed_special",
"y": 90
},
"face=floor,facing=north,powered=false": {
"model": "reframed:button_special"
},
"face=floor,facing=north,powered=true": {
"model": "reframed:button_pressed_special"
},
"face=floor,facing=south,powered=false": {
"model": "reframed:button_special",
"y": 180
},
"face=floor,facing=south,powered=true": {
"model": "reframed:button_pressed_special",
"y": 180
},
"face=floor,facing=west,powered=false": {
"model": "reframed:button_special",
"y": 270
},
"face=floor,facing=west,powered=true": {
"model": "reframed:button_pressed_special",
"y": 270
},
"face=wall,facing=east,powered=false": {
"model": "reframed:button_special",
"uvlock": true,
"x": 90,
"y": 90
},
"face=wall,facing=east,powered=true": {
"model": "reframed:button_pressed_special",
"uvlock": true,
"x": 90,
"y": 90
},
"face=wall,facing=north,powered=false": {
"model": "reframed:button_special",
"uvlock": true,
"x": 90
},
"face=wall,facing=north,powered=true": {
"model": "reframed:button_pressed_special",
"uvlock": true,
"x": 90
},
"face=wall,facing=south,powered=false": {
"model": "reframed:button_special",
"uvlock": true,
"x": 90,
"y": 180
},
"face=wall,facing=south,powered=true": {
"model": "reframed:button_pressed_special",
"uvlock": true,
"x": 90,
"y": 180
},
"face=wall,facing=west,powered=false": {
"model": "reframed:button_special",
"uvlock": true,
"x": 90,
"y": 270
},
"face=wall,facing=west,powered=true": {
"model": "reframed:button_pressed_special",
"uvlock": true,
"x": 90,
"y": 270
}
}
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"candles=1": {
"model": "reframed:one_candle_special"
},
"candles=2": {
"model": "reframed:two_candles_special"
},
"candles=3": {
"model": "reframed:three_candles_special"
},
"candles=4": {
"model": "reframed:four_candles_special"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "reframed:carpet_special"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "reframed:cube_special"
}
}
}

View File

@ -0,0 +1,124 @@
{
"variants": {
"facing=east,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special"
},
"facing=east,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special",
"y": 90
},
"facing=east,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special"
},
"facing=east,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special",
"y": 270
},
"facing=east,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special"
},
"facing=east,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special",
"y": 90
},
"facing=east,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special"
},
"facing=east,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special",
"y": 270
},
"facing=north,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special",
"y": 270
},
"facing=north,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special"
},
"facing=north,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special",
"y": 270
},
"facing=north,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special",
"y": 180
},
"facing=north,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special",
"y": 270
},
"facing=north,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special"
},
"facing=north,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special",
"y": 270
},
"facing=north,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special",
"y": 180
},
"facing=south,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special",
"y": 90
},
"facing=south,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special",
"y": 180
},
"facing=south,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special",
"y": 90
},
"facing=south,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special"
},
"facing=south,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special",
"y": 90
},
"facing=south,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special",
"y": 180
},
"facing=south,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special",
"y": 90
},
"facing=south,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special"
},
"facing=west,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special",
"y": 180
},
"facing=west,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special",
"y": 270
},
"facing=west,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special",
"y": 180
},
"facing=west,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special",
"y": 90
},
"facing=west,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special",
"y": 180
},
"facing=west,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special",
"y": 270
},
"facing=west,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special",
"y": 180
},
"facing=west,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special",
"y": 90
}
}
}

View File

@ -0,0 +1,48 @@
{
"multipart": [
{
"apply": {
"model": "reframed:fence_post_special"
}
},
{
"apply": {
"model": "reframed:fence_side_special",
"uvlock": true
},
"when": {
"north": "true"
}
},
{
"apply": {
"model": "reframed:fence_side_special",
"uvlock": true,
"y": 90
},
"when": {
"east": "true"
}
},
{
"apply": {
"model": "reframed:fence_side_special",
"uvlock": true,
"y": 180
},
"when": {
"south": "true"
}
},
{
"apply": {
"model": "reframed:fence_side_special",
"uvlock": true,
"y": 270
},
"when": {
"west": "true"
}
}
]
}

View File

@ -0,0 +1,80 @@
{
"variants": {
"facing=east,in_wall=false,open=false": {
"model": "reframed:fence_gate_special",
"uvlock": true,
"y": 270
},
"facing=east,in_wall=false,open=true": {
"model": "reframed:fence_gate_open_special",
"uvlock": true,
"y": 270
},
"facing=east,in_wall=true,open=false": {
"model": "reframed:fence_gate_wall_special",
"uvlock": true,
"y": 270
},
"facing=east,in_wall=true,open=true": {
"model": "reframed:fence_gate_wall_open_special",
"uvlock": true,
"y": 270
},
"facing=north,in_wall=false,open=false": {
"model": "reframed:fence_gate_special",
"uvlock": true,
"y": 180
},
"facing=north,in_wall=false,open=true": {
"model": "reframed:fence_gate_open_special",
"uvlock": true,
"y": 180
},
"facing=north,in_wall=true,open=false": {
"model": "reframed:fence_gate_wall_special",
"uvlock": true,
"y": 180
},
"facing=north,in_wall=true,open=true": {
"model": "reframed:fence_gate_wall_open_special",
"uvlock": true,
"y": 180
},
"facing=south,in_wall=false,open=false": {
"model": "reframed:fence_gate_special",
"uvlock": true
},
"facing=south,in_wall=false,open=true": {
"model": "reframed:fence_gate_open_special",
"uvlock": true
},
"facing=south,in_wall=true,open=false": {
"model": "reframed:fence_gate_wall_special",
"uvlock": true
},
"facing=south,in_wall=true,open=true": {
"model": "reframed:fence_gate_wall_open_special",
"uvlock": true
},
"facing=west,in_wall=false,open=false": {
"model": "reframed:fence_gate_special",
"uvlock": true,
"y": 90
},
"facing=west,in_wall=false,open=true": {
"model": "reframed:fence_gate_open_special",
"uvlock": true,
"y": 90
},
"facing=west,in_wall=true,open=false": {
"model": "reframed:fence_gate_wall_special",
"uvlock": true,
"y": 90
},
"facing=west,in_wall=true,open=true": {
"model": "reframed:fence_gate_wall_open_special",
"uvlock": true,
"y": 90
}
}
}

View File

@ -0,0 +1,124 @@
{
"variants": {
"facing=east,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special"
},
"facing=east,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special",
"y": 90
},
"facing=east,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special"
},
"facing=east,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special",
"y": 270
},
"facing=east,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special"
},
"facing=east,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special",
"y": 90
},
"facing=east,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special"
},
"facing=east,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special",
"y": 270
},
"facing=north,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special",
"y": 270
},
"facing=north,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special"
},
"facing=north,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special",
"y": 270
},
"facing=north,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special",
"y": 180
},
"facing=north,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special",
"y": 270
},
"facing=north,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special"
},
"facing=north,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special",
"y": 270
},
"facing=north,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special",
"y": 180
},
"facing=south,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special",
"y": 90
},
"facing=south,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special",
"y": 180
},
"facing=south,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special",
"y": 90
},
"facing=south,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special"
},
"facing=south,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special",
"y": 90
},
"facing=south,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special",
"y": 180
},
"facing=south,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special",
"y": 90
},
"facing=south,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special"
},
"facing=west,half=lower,hinge=left,open=false": {
"model": "reframed:door_bottom_left_special",
"y": 180
},
"facing=west,half=lower,hinge=left,open=true": {
"model": "reframed:door_bottom_left_open_special",
"y": 270
},
"facing=west,half=lower,hinge=right,open=false": {
"model": "reframed:door_bottom_right_special",
"y": 180
},
"facing=west,half=lower,hinge=right,open=true": {
"model": "reframed:door_bottom_right_open_special",
"y": 90
},
"facing=west,half=upper,hinge=left,open=false": {
"model": "reframed:door_top_left_special",
"y": 180
},
"facing=west,half=upper,hinge=left,open=true": {
"model": "reframed:door_top_left_open_special",
"y": 270
},
"facing=west,half=upper,hinge=right,open=false": {
"model": "reframed:door_top_right_special",
"y": 180
},
"facing=west,half=upper,hinge=right,open=true": {
"model": "reframed:door_top_right_open_special",
"y": 90
}
}
}

View File

@ -0,0 +1,69 @@
{
"variants": {
"facing=east,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special",
"y": 90
},
"facing=east,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special",
"y": 90
},
"facing=east,half=top,open=false": {
"model": "reframed:trapdoor_top_special",
"y": 90
},
"facing=east,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 270
},
"facing=north,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special"
},
"facing=north,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special"
},
"facing=north,half=top,open=false": {
"model": "reframed:trapdoor_top_special"
},
"facing=north,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 180
},
"facing=south,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special",
"y": 180
},
"facing=south,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special",
"y": 180
},
"facing=south,half=top,open=false": {
"model": "reframed:trapdoor_top_special",
"y": 180
},
"facing=south,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 0
},
"facing=west,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special",
"y": 270
},
"facing=west,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special",
"y": 270
},
"facing=west,half=top,open=false": {
"model": "reframed:trapdoor_top_special",
"y": 270
},
"facing=west,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 90
}
}
}

View File

@ -0,0 +1,110 @@
{
"variants": {
"face=ceiling,facing=east,powered=false": {
"model": "reframed:lever_on_special",
"x": 180,
"y": 270
},
"face=ceiling,facing=east,powered=true": {
"model": "reframed:lever_special",
"x": 180,
"y": 270
},
"face=ceiling,facing=north,powered=false": {
"model": "reframed:lever_on_special",
"x": 180,
"y": 180
},
"face=ceiling,facing=north,powered=true": {
"model": "reframed:lever_special",
"x": 180,
"y": 180
},
"face=ceiling,facing=south,powered=false": {
"model": "reframed:lever_on_special",
"x": 180
},
"face=ceiling,facing=south,powered=true": {
"model": "reframed:lever_special",
"x": 180
},
"face=ceiling,facing=west,powered=false": {
"model": "reframed:lever_on_special",
"x": 180,
"y": 90
},
"face=ceiling,facing=west,powered=true": {
"model": "reframed:lever_special",
"x": 180,
"y": 90
},
"face=floor,facing=east,powered=false": {
"model": "reframed:lever_on_special",
"y": 90
},
"face=floor,facing=east,powered=true": {
"model": "reframed:lever_special",
"y": 90
},
"face=floor,facing=north,powered=false": {
"model": "reframed:lever_on_special"
},
"face=floor,facing=north,powered=true": {
"model": "reframed:lever_special"
},
"face=floor,facing=south,powered=false": {
"model": "reframed:lever_on_special",
"y": 180
},
"face=floor,facing=south,powered=true": {
"model": "reframed:lever_special",
"y": 180
},
"face=floor,facing=west,powered=false": {
"model": "reframed:lever_on_special",
"y": 270
},
"face=floor,facing=west,powered=true": {
"model": "reframed:lever_special",
"y": 270
},
"face=wall,facing=east,powered=false": {
"model": "reframed:lever_on_special",
"x": 90,
"y": 90
},
"face=wall,facing=east,powered=true": {
"model": "reframed:lever_special",
"x": 90,
"y": 90
},
"face=wall,facing=north,powered=false": {
"model": "reframed:lever_on_special",
"x": 90
},
"face=wall,facing=north,powered=true": {
"model": "reframed:lever_special",
"x": 90
},
"face=wall,facing=south,powered=false": {
"model": "reframed:lever_on_special",
"x": 90,
"y": 180
},
"face=wall,facing=south,powered=true": {
"model": "reframed:lever_special",
"x": 90,
"y": 180
},
"face=wall,facing=west,powered=false": {
"model": "reframed:lever_on_special",
"x": 90,
"y": 270
},
"face=wall,facing=west,powered=true": {
"model": "reframed:lever_special",
"x": 90,
"y": 270
}
}
}

View File

@ -0,0 +1,77 @@
{
"multipart": [
{
"apply": {
"model": "reframed:glass_pane_post_special"
}
},
{
"apply": {
"model": "reframed:glass_pane_side_special"
},
"when": {
"north": "true"
}
},
{
"apply": {
"model": "reframed:glass_pane_side_special",
"y": 90
},
"when": {
"east": "true"
}
},
{
"apply": {
"model": "reframed:glass_pane_side_alt_special"
},
"when": {
"south": "true"
}
},
{
"apply": {
"model": "reframed:glass_pane_side_alt_special",
"y": 90
},
"when": {
"west": "true"
}
},
{
"apply": {
"model": "reframed:glass_pane_noside_special"
},
"when": {
"north": "false"
}
},
{
"apply": {
"model": "reframed:glass_pane_noside_alt_special"
},
"when": {
"east": "false"
}
},
{
"apply": {
"model": "reframed:glass_pane_noside_alt_special",
"y": 90
},
"when": {
"south": "false"
}
},
{
"apply": {
"model": "reframed:glass_pane_noside_special",
"y": 270
},
"when": {
"west": "false"
}
}
]
}

View File

@ -0,0 +1,19 @@
{
"variants": {
"axis=x": {
"model": "reframed:fence_post_special",
"x": 90,
"y": 90,
"uvlock": true
},
"axis=y": {
"model": "reframed:fence_post_special",
"uvlock": true
},
"axis=z": {
"model": "reframed:fence_post_special",
"uvlock": true,
"x": 90
}
}
}

View File

@ -0,0 +1,10 @@
{
"variants": {
"powered=false": {
"model": "reframed:pressure_plate_up_special"
},
"powered=true": {
"model": "reframed:pressure_plate_down_special"
}
}
}

View File

@ -0,0 +1,69 @@
{
"variants": {
"facing=east,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special",
"y": 90
},
"facing=east,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special",
"y": 90
},
"facing=east,half=top,open=false": {
"model": "reframed:trapdoor_top_special",
"y": 90
},
"facing=east,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 270
},
"facing=north,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special"
},
"facing=north,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special"
},
"facing=north,half=top,open=false": {
"model": "reframed:trapdoor_top_special"
},
"facing=north,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 180
},
"facing=south,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special",
"y": 180
},
"facing=south,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special",
"y": 180
},
"facing=south,half=top,open=false": {
"model": "reframed:trapdoor_top_special",
"y": 180
},
"facing=south,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 0
},
"facing=west,half=bottom,open=false": {
"model": "reframed:trapdoor_bottom_special",
"y": 270
},
"facing=west,half=bottom,open=true": {
"model": "reframed:trapdoor_open_special",
"y": 270
},
"facing=west,half=top,open=false": {
"model": "reframed:trapdoor_top_special",
"y": 270
},
"facing=west,half=top,open=true": {
"model": "reframed:trapdoor_open_special",
"x": 180,
"y": 90
}
}
}

View File

@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": {
"model": "reframed:wall_post_special"
},
"when": {
"up": "true"
}
},
{
"apply": {
"model": "reframed:wall_side_special",
"uvlock": true
},
"when": {
"north": "low"
}
},
{
"apply": {
"model": "reframed:wall_side_special",
"uvlock": true,
"y": 90
},
"when": {
"east": "low"
}
},
{
"apply": {
"model": "reframed:wall_side_special",
"uvlock": true,
"y": 180
},
"when": {
"south": "low"
}
},
{
"apply": {
"model": "reframed:wall_side_special",
"uvlock": true,
"y": 270
},
"when": {
"west": "low"
}
},
{
"apply": {
"model": "reframed:wall_side_tall_special",
"uvlock": true
},
"when": {
"north": "tall"
}
},
{
"apply": {
"model": "reframed:wall_side_tall_special",
"uvlock": true,
"y": 90
},
"when": {
"east": "tall"
}
},
{
"apply": {
"model": "reframed:wall_side_tall_special",
"uvlock": true,
"y": 180
},
"when": {
"south": "tall"
}
},
{
"apply": {
"model": "reframed:wall_side_tall_special",
"uvlock": true,
"y": 270
},
"when": {
"west": "tall"
}
}
]
}

View File

@ -0,0 +1,22 @@
{
"itemGroup.reframed.tab": "Frames",
"block.reframed.button": "Button Frame",
"block.reframed.candle": "Candle Frame",
"block.reframed.carpet": "Carpet Frame",
"block.reframed.cube": "Cube Frame",
"block.reframed.door": "Door Frame",
"block.reframed.fence": "Fence Frame",
"block.reframed.fence_gate": "Fence Gate Frame",
"block.reframed.iron_door": "Iron Door Frame",
"block.reframed.iron_trapdoor": "Iron Trapdoor Frame",
"block.reframed.lever": "Lever Frame",
"block.reframed.pane": "Pane Frame",
"block.reframed.post": "Post Frame",
"block.reframed.pressure_plate": "Pressure Plate Frame",
"block.reframed.slab": "Slab Frame",
"block.reframed.stairs": "Stairs Frame",
"block.reframed.trapdoor": "Trapdoor Frame",
"block.reframed.wall": "Wall Frame"
}

View File

@ -0,0 +1,41 @@
{
"parent": "minecraft:block/block",
"textures": {
"particle": "#texture"
},
"elements": [
{
"from": [6, 0, 6],
"to": [10, 16, 10],
"faces": {
"down": {
"uv": [6, 6, 10, 10],
"texture": "#texture",
"cullface": "down"
},
"up": {
"uv": [6, 6, 10, 10],
"texture": "#texture",
"cullface": "up"
},
"north": {
"uv": [6, 0, 10, 16],
"texture": "#texture"
},
"south": {
"uv": [6, 0, 10, 16],
"texture": "#texture"
},
"west": {
"uv": [6, 0, 10, 16],
"texture": "#texture"
},
"east": {
"uv": [6, 0, 10, 16],
"texture": "#texture"
}
},
"__comment": "Center post"
}
]
}

View File

@ -0,0 +1,60 @@
{
"elements": [
{
"from": [7, 12, 0],
"to": [9, 15, 9],
"faces": {
"down": {
"uv": [7, 0, 9, 9],
"texture": "#down"
},
"up": {
"uv": [7, 0, 9, 9],
"texture": "#up"
},
"north": {
"uv": [7, 1, 9, 4],
"texture": "#north",
"cullface": "north"
},
"west": {
"uv": [0, 1, 9, 4],
"texture": "#west"
},
"east": {
"uv": [0, 1, 9, 4],
"texture": "#east"
}
},
"__comment": "top bar"
},
{
"from": [7, 6, 0],
"to": [9, 9, 9],
"faces": {
"down": {
"uv": [7, 0, 9, 9],
"texture": "#down"
},
"up": {
"uv": [7, 0, 9, 9],
"texture": "#up"
},
"north": {
"uv": [7, 7, 9, 10],
"texture": "#north",
"cullface": "north"
},
"west": {
"uv": [0, 7, 9, 10],
"texture": "#west"
},
"east": {
"uv": [0, 7, 9, 10],
"texture": "#east"
}
},
"__comment": "lower bar"
}
]
}

View File

@ -0,0 +1,32 @@
{
"ambientocclusion": false,
"elements": [
{
"from": [7, 0, 0],
"to": [9, 16, 7],
"faces": {
"down": {
"uv": [7, 0, 9, 7],
"texture": "#down"
},
"up": {
"uv": [7, 0, 9, 7],
"texture": "#up"
},
"north": {
"uv": [7, 0, 9, 16],
"texture": "#north",
"cullface": "north"
},
"west": {
"uv": [16, 0, 9, 16],
"texture": "#west"
},
"east": {
"uv": [9, 0, 16, 16],
"texture": "#east"
}
}
}
]
}

View File

@ -0,0 +1,32 @@
{
"ambientocclusion": false,
"elements": [
{
"from": [7, 0, 9],
"to": [9, 16, 16],
"faces": {
"down": {
"uv": [7, 0, 9, 7],
"texture": "#down"
},
"up": {
"uv": [7, 0, 9, 7],
"texture": "#up"
},
"south": {
"uv": [7, 0, 9, 16],
"texture": "#south",
"cullface": "south"
},
"west": {
"uv": [7, 0, 0, 16],
"texture": "#west"
},
"east": {
"uv": [0, 0, 7, 16],
"texture": "#east"
}
}
}
]
}

View File

@ -0,0 +1,71 @@
{
"parent": "block/block",
"ambientocclusion": false,
"textures": {
"lever": "block/lever"
},
"elements": [
{
"from": [5, -0.02, 4],
"to": [11, 2.98, 12],
"faces": {
"down": {
"uv": [5, 4, 11, 12],
"texture": "#down",
"cullface": "down"
},
"up": {
"uv": [5, 4, 11, 12],
"texture": "#up"
},
"north": {
"uv": [5, 0, 11, 3],
"texture": "#north"
},
"south": {
"uv": [5, 0, 11, 3],
"texture": "#south"
},
"west": {
"uv": [4, 0, 12, 3],
"texture": "#west"
},
"east": {
"uv": [4, 0, 12, 3],
"texture": "#east"
}
}
},
{
"from": [7, 1, 7],
"to": [9, 11, 9],
"rotation": {
"origin": [8, 1, 8],
"axis": "x",
"angle": -45
},
"faces": {
"up": {
"uv": [7, 6, 9, 8],
"texture": "#lever"
},
"north": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
},
"south": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
},
"west": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
},
"east": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
}
}
}
]
}

View File

@ -0,0 +1,71 @@
{
"parent": "block/block",
"ambientocclusion": false,
"textures": {
"lever": "block/lever"
},
"elements": [
{
"from": [5, -0.02, 4],
"to": [11, 2.98, 12],
"faces": {
"down": {
"uv": [5, 4, 11, 12],
"texture": "#down",
"cullface": "down"
},
"up": {
"uv": [5, 4, 11, 12],
"texture": "#up"
},
"north": {
"uv": [5, 0, 11, 3],
"texture": "#north"
},
"south": {
"uv": [5, 0, 11, 3],
"texture": "#south"
},
"west": {
"uv": [4, 0, 12, 3],
"texture": "#west"
},
"east": {
"uv": [4, 0, 12, 3],
"texture": "#east"
}
}
},
{
"from": [7, 1, 7],
"to": [9, 11, 9],
"rotation": {
"origin": [8, 1, 8],
"axis": "x",
"angle": 45
},
"faces": {
"up": {
"uv": [7, 6, 9, 8],
"texture": "#lever"
},
"north": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
},
"south": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
},
"west": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
},
"east": {
"uv": [7, 6, 9, 16],
"texture": "#lever"
}
}
}
]
}

View File

@ -1,35 +0,0 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "#side"
},
"elements": [
{
"from": [8, 0, 0],
"to": [16, 8, 16],
"faces": {
"north": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "north"},
"east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"},
"south": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "south"},
"west": {"uv": [0, 8, 16, 16], "texture": "#side"},
"up": {"uv": [8, 0, 16, 16], "texture": "#top"},
"down": {"uv": [8, 0, 16, 16], "texture": "#bottom", "cullface": "down"}
}
}
],
"display": {
"thirdperson_lefthand": {
"rotation": [75, -135, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"gui": {
"rotation": [30, 135, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"rotation": [0, -90, 0]
}
}
}

View File

@ -1,35 +0,0 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "#side"
},
"elements": [
{
"from": [0, 0, 0],
"to": [8, 8, 16],
"faces": {
"north": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "north"},
"east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"},
"south": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "south"},
"west": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "west"},
"up": {"uv": [0, 0, 8, 16], "texture": "#top"},
"down": {"uv": [0, 0, 8, 16], "texture": "#bottom", "cullface": "down"}
}
}
],
"display": {
"thirdperson_lefthand": {
"rotation": [75, -135, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"gui": {
"rotation": [30, 135, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"rotation": [0, -90, 0]
}
}
}

View File

@ -1,35 +0,0 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "#side"
},
"elements": [
{
"from": [8, 0, 0],
"to": [16, 16, 8],
"faces": {
"north": {"uv": [0, 0, 8, 16], "texture": "#side", "cullface": "north"},
"east": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "east"},
"south": {"uv": [8, 0, 16, 16], "texture": "#side"},
"west": {"uv": [0, 0, 8, 16], "texture": "#side"},
"up": {"uv": [8, 0, 16, 8], "texture": "#top", "cullface": "up"},
"down": {"uv": [8, 8, 16, 16], "texture": "#bottom", "cullface": "down"}
}
}
],
"display": {
"thirdperson_lefthand": {
"rotation": [75, -135, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"gui": {
"rotation": [30, 135, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"rotation": [0, -90, 0]
}
}
}

View File

@ -1,35 +0,0 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "#side"
},
"elements": [
{
"from": [8, 0, 8],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 8, 16], "texture": "#side"},
"east": {"uv": [0, 0, 8, 16], "texture": "#side", "cullface": "east"},
"south": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "south"},
"west": {"uv": [8, 0, 16, 16], "texture": "#side"},
"up": {"uv": [8, 8, 16, 16], "texture": "#top", "cullface": "up"},
"down": {"uv": [8, 0, 16, 8], "texture": "#bottom", "cullface": "down"}
}
}
],
"display": {
"thirdperson_lefthand": {
"rotation": [75, -135, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"gui": {
"rotation": [30, 135, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"rotation": [0, -90, 0]
}
}
}

View File

@ -0,0 +1,43 @@
{
"parent": "block/block",
"elements": [
{
"from": [0, 0, 13],
"to": [16, 16, 16],
"faces": {
"down": {
"uv": [0, 16, 16, 13],
"texture": "#north",
"cullface": "down",
"rotation": 180
},
"up": {
"uv": [0, 16, 16, 13],
"texture": "#south",
"cullface": "up"
},
"north": {
"uv": [0, 0, 16, 16],
"texture": "#down"
},
"south": {
"uv": [0, 0, 16, 16],
"texture": "#up",
"cullface": "south"
},
"west": {
"uv": [0, 16, 16, 13],
"texture": "#west",
"cullface": "west",
"rotation": 270
},
"east": {
"uv": [0, 16, 16, 13],
"texture": "#east",
"cullface": "east",
"rotation": 90
}
}
}
]
}

View File

@ -0,0 +1,28 @@
{
"elements": [
{
"from": [5, 0, 0],
"to": [11, 14, 8],
"faces": {
"down": {
"texture": "#down",
"cullface": "down"
},
"up": {
"texture": "#up"
},
"north": {
"texture": "#north",
"cullface": "north"
},
"west": {
"texture": "#west"
},
"east": {
"texture": "#east"
}
},
"__comment": "wall"
}
]
}

View File

@ -0,0 +1,28 @@
{
"elements": [
{
"from": [5, 0, 0],
"to": [11, 16, 8],
"faces": {
"down": {
"texture": "#down",
"cullface": "down"
},
"up": {
"texture": "#up",
"cullface": "up"
},
"north": {
"texture": "#north",
"cullface": "north"
},
"west": {
"texture": "#west"
},
"east": {
"texture": "#east"
}
}
}
]
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reframed:item/candle"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reframed:item/door"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reframed:item/door"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reframed:item/lever"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reframed:block/framed_block"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:candle"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:iron_door"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:fence_gate"
]
}

View File

@ -0,0 +1,20 @@
{
"replace": false,
"values": [
"reframed:button",
"reframed:candle",
"reframed:carpet",
"reframed:cube",
"reframed:door",
"reframed:fence",
"reframed:fence_gate",
"reframed:lever",
"reframed:pane",
"reframed:post",
"reframed:pressure_plate",
"reframed:slab",
"reframed:stairs",
"reframed:trapdoor",
"reframed:wall"
]
}

View File

@ -0,0 +1,7 @@
{
"replace": false,
"values": [
"reframed:iron_door",
"reframed:iron_trapdoor"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:iron_trapdoor"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:wall"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:button"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:door"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:fence"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:pressure_plate"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:slab"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:stairs"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:trapdoor"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:carpet"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:candle"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:iron_door"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:fence_gate"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:iron_trapdoor"
]
}

View File

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"reframed:wall"
]
}

Some files were not shown because too many files have changed in this diff Show More