Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
346
src/main/java/com/tiedup/remake/blocks/BlockIronBarDoor.java
Normal file
346
src/main/java/com/tiedup/remake/blocks/BlockIronBarDoor.java
Normal file
@@ -0,0 +1,346 @@
|
||||
package com.tiedup.remake.blocks;
|
||||
|
||||
import com.tiedup.remake.blocks.entity.IronBarDoorBlockEntity;
|
||||
import com.tiedup.remake.core.SystemMessageManager;
|
||||
import com.tiedup.remake.items.ItemCellKey;
|
||||
import com.tiedup.remake.items.ItemKey;
|
||||
import com.tiedup.remake.items.ItemMasterKey;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.*;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Iron Bar Door - A door made of iron bars that can be locked.
|
||||
*
|
||||
* Phase: Kidnapper Revamp - Cell System
|
||||
*
|
||||
* Features:
|
||||
* - Lockable with ItemKey (stores key UUID)
|
||||
* - Can be unlocked with matching key, ItemCellKey, or ItemMasterKey
|
||||
* - When locked, cannot be opened by redstone or by hand
|
||||
* - Visually connects to iron bars (like vanilla iron bars)
|
||||
* - Uses DoorBlock mechanics for open/close state
|
||||
*/
|
||||
public class BlockIronBarDoor extends DoorBlock implements EntityBlock {
|
||||
|
||||
// VoxelShapes for different orientations - centered like iron bars (7-9 = 2 pixels thick)
|
||||
protected static final VoxelShape SOUTH_AABB = Block.box(
|
||||
0.0,
|
||||
0.0,
|
||||
7.0,
|
||||
16.0,
|
||||
16.0,
|
||||
9.0
|
||||
);
|
||||
protected static final VoxelShape NORTH_AABB = Block.box(
|
||||
0.0,
|
||||
0.0,
|
||||
7.0,
|
||||
16.0,
|
||||
16.0,
|
||||
9.0
|
||||
);
|
||||
protected static final VoxelShape WEST_AABB = Block.box(
|
||||
7.0,
|
||||
0.0,
|
||||
0.0,
|
||||
9.0,
|
||||
16.0,
|
||||
16.0
|
||||
);
|
||||
protected static final VoxelShape EAST_AABB = Block.box(
|
||||
7.0,
|
||||
0.0,
|
||||
0.0,
|
||||
9.0,
|
||||
16.0,
|
||||
16.0
|
||||
);
|
||||
|
||||
public BlockIronBarDoor() {
|
||||
super(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.METAL)
|
||||
.strength(5.0f, 45.0f)
|
||||
.sound(SoundType.METAL)
|
||||
.requiresCorrectToolForDrops()
|
||||
.noOcclusion(),
|
||||
BlockSetType.IRON
|
||||
);
|
||||
}
|
||||
|
||||
// ==================== SHAPE ====================
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(
|
||||
BlockState state,
|
||||
BlockGetter level,
|
||||
BlockPos pos,
|
||||
CollisionContext context
|
||||
) {
|
||||
Direction facing = state.getValue(FACING);
|
||||
boolean open = state.getValue(OPEN);
|
||||
boolean hingeRight = state.getValue(HINGE) == DoorHingeSide.RIGHT;
|
||||
|
||||
Direction effectiveDirection;
|
||||
if (open) {
|
||||
effectiveDirection = hingeRight
|
||||
? facing.getCounterClockWise()
|
||||
: facing.getClockWise();
|
||||
} else {
|
||||
effectiveDirection = facing;
|
||||
}
|
||||
|
||||
return switch (effectiveDirection) {
|
||||
case NORTH -> NORTH_AABB;
|
||||
case SOUTH -> SOUTH_AABB;
|
||||
case WEST -> WEST_AABB;
|
||||
case EAST -> EAST_AABB;
|
||||
default -> SOUTH_AABB;
|
||||
};
|
||||
}
|
||||
|
||||
// ==================== INTERACTION ====================
|
||||
|
||||
@Override
|
||||
public InteractionResult use(
|
||||
BlockState state,
|
||||
Level level,
|
||||
BlockPos pos,
|
||||
Player player,
|
||||
InteractionHand hand,
|
||||
BlockHitResult hit
|
||||
) {
|
||||
// Get the BlockEntity
|
||||
BlockEntity be = level.getBlockEntity(
|
||||
getBlockEntityPos(state, pos, level)
|
||||
);
|
||||
if (!(be instanceof IronBarDoorBlockEntity doorEntity)) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
|
||||
// Handle key interactions
|
||||
if (heldItem.getItem() instanceof ItemMasterKey) {
|
||||
// Master key can always unlock
|
||||
if (doorEntity.isLocked()) {
|
||||
if (!level.isClientSide) {
|
||||
doorEntity.setLocked(false);
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.INFO,
|
||||
"Door unlocked with master key"
|
||||
);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
} else if (heldItem.getItem() instanceof ItemCellKey) {
|
||||
// Cell key can unlock any iron bar door
|
||||
if (doorEntity.isLocked()) {
|
||||
if (!level.isClientSide) {
|
||||
doorEntity.setLocked(false);
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.INFO,
|
||||
"Door unlocked with cell key"
|
||||
);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
} else if (heldItem.getItem() instanceof ItemKey key) {
|
||||
UUID keyUUID = key.getKeyUUID(heldItem);
|
||||
|
||||
if (doorEntity.isLocked()) {
|
||||
// Try to unlock
|
||||
if (doorEntity.matchesKey(keyUUID)) {
|
||||
if (!level.isClientSide) {
|
||||
doorEntity.setLocked(false);
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.INFO,
|
||||
"Door unlocked"
|
||||
);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
} else {
|
||||
if (!level.isClientSide) {
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.ERROR,
|
||||
"This key doesn't fit this lock"
|
||||
);
|
||||
}
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
} else {
|
||||
// Lock the door with this key
|
||||
if (!level.isClientSide) {
|
||||
doorEntity.setLockedByKeyUUID(keyUUID);
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.INFO,
|
||||
"Door locked"
|
||||
);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
}
|
||||
|
||||
// If locked and no valid key, deny access
|
||||
if (doorEntity.isLocked()) {
|
||||
if (!level.isClientSide) {
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.ERROR,
|
||||
"This door is locked"
|
||||
);
|
||||
}
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
// Iron doors don't open by hand normally, but we allow it if unlocked
|
||||
// Toggle the door state
|
||||
if (!level.isClientSide) {
|
||||
boolean newOpen = !state.getValue(OPEN);
|
||||
setOpen(player, level, state, pos, newOpen);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BlockEntity position (handles double-height doors).
|
||||
*/
|
||||
private BlockPos getBlockEntityPos(
|
||||
BlockState state,
|
||||
BlockPos pos,
|
||||
Level level
|
||||
) {
|
||||
// LOW FIX: Check if HALF property exists before accessing (WorldEdit/SetBlock safety)
|
||||
if (!state.hasProperty(HALF)) {
|
||||
// Invalid state - assume lower half
|
||||
return pos;
|
||||
}
|
||||
|
||||
// BlockEntity is always on the lower half
|
||||
if (state.getValue(HALF) == DoubleBlockHalf.UPPER) {
|
||||
return pos.below();
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
// ==================== REDSTONE ====================
|
||||
|
||||
@Override
|
||||
public void neighborChanged(
|
||||
BlockState state,
|
||||
Level level,
|
||||
BlockPos pos,
|
||||
Block neighborBlock,
|
||||
BlockPos neighborPos,
|
||||
boolean movedByPiston
|
||||
) {
|
||||
// Check if locked before allowing redstone control
|
||||
BlockEntity be = level.getBlockEntity(
|
||||
getBlockEntityPos(state, pos, level)
|
||||
);
|
||||
if (
|
||||
be instanceof IronBarDoorBlockEntity doorEntity &&
|
||||
doorEntity.isLocked()
|
||||
) {
|
||||
// Door is locked, ignore redstone
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow normal redstone behavior if unlocked
|
||||
super.neighborChanged(
|
||||
state,
|
||||
level,
|
||||
pos,
|
||||
neighborBlock,
|
||||
neighborPos,
|
||||
movedByPiston
|
||||
);
|
||||
}
|
||||
|
||||
// ==================== BLOCK ENTITY ====================
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
// Only create block entity for the lower half
|
||||
if (state.getValue(HALF) == DoubleBlockHalf.LOWER) {
|
||||
return new IronBarDoorBlockEntity(pos, state);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==================== PLACEMENT ====================
|
||||
|
||||
@Override
|
||||
public void setPlacedBy(
|
||||
Level level,
|
||||
BlockPos pos,
|
||||
BlockState state,
|
||||
@Nullable net.minecraft.world.entity.LivingEntity placer,
|
||||
ItemStack stack
|
||||
) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack);
|
||||
// BlockEntity is automatically created for lower half
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(
|
||||
BlockState state,
|
||||
Level level,
|
||||
BlockPos pos,
|
||||
BlockState newState,
|
||||
boolean movedByPiston
|
||||
) {
|
||||
if (!state.is(newState.getBlock())) {
|
||||
// Block entity is removed automatically
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
// ==================== VISUAL ====================
|
||||
|
||||
@Override
|
||||
public float getShadeBrightness(
|
||||
BlockState state,
|
||||
BlockGetter level,
|
||||
BlockPos pos
|
||||
) {
|
||||
// Allow some light through like iron bars
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean propagatesSkylightDown(
|
||||
BlockState state,
|
||||
BlockGetter level,
|
||||
BlockPos pos
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user