Skip to content

Commit 28a5aa6

Browse files
committed
优化脚手架放置
1 parent f15bd31 commit 28a5aa6

5 files changed

Lines changed: 163 additions & 144 deletions

File tree

src/main/java/com/teammoeg/frostedheart/bootstrap/common/FHBlocks.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,7 @@ private static boolean never(BlockState state, BlockGetter getter, BlockPos pos)
19421942
.blockstate(FHBlockStateGen.simpleCubeAll("concrete/concrete_cracked_"+i))
19431943
.simpleItem()
19441944
.register());
1945+
19451946
public static final BlockEntry<FHScaffoldingStairsBlock> METAL_SCAFFOLDING_STAIRS = REGISTRATE.block("metal_scaffolding_stairs", FHScaffoldingStairsBlock::new)
19461947
.properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY)
19471948
.requiresCorrectToolForDrops()
@@ -1958,8 +1959,10 @@ private static boolean never(BlockState state, BlockGetter getter, BlockPos pos)
19581959
.properties(BlockBehaviour.Properties::dynamicShape)
19591960
.tag(FHTags.Blocks.SCAFFOLDING.tag, BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.NEEDS_STONE_TOOL, BlockTags.CLIMBABLE, AllTags.AllBlockTags.WRENCH_PICKUP.tag)
19601961
.blockstate(existed())
1961-
.simpleItem()
1962+
.item(FHScaffoldingBlockItem::new)
1963+
.build()
19621964
.register();
1965+
19631966
public static final BlockEntry<FHScaffoldingStairsBlock> WOODEN_SCAFFOLDING_STAIRS = REGISTRATE.block("wooden_scaffolding_stairs", FHScaffoldingStairsBlock::new)
19641967
.properties(p -> p.mapColor(MapColor.PODZOL)
19651968
.sound(SoundType.WOOD)
@@ -1976,8 +1979,10 @@ private static boolean never(BlockState state, BlockGetter getter, BlockPos pos)
19761979
.properties(BlockBehaviour.Properties::dynamicShape)
19771980
.tag(FHTags.Blocks.SCAFFOLDING.tag, BlockTags.MINEABLE_WITH_AXE, BlockTags.CLIMBABLE, AllTags.AllBlockTags.WRENCH_PICKUP.tag)
19781981
.blockstate(existed())
1979-
.simpleItem()
1982+
.item(FHScaffoldingBlockItem::new)
1983+
.build()
19801984
.register();
1985+
19811986
public static final BlockEntry<FHScaffoldingStairsBlock> TIMBER_METAL_SCAFFOLDING_STAIRS = REGISTRATE.block("timber_metal_scaffolding_stairs", FHScaffoldingStairsBlock::new)
19821987
.properties(p -> p.mapColor(MapColor.PODZOL)
19831988
.noOcclusion()
@@ -1993,7 +1998,8 @@ private static boolean never(BlockState state, BlockGetter getter, BlockPos pos)
19931998
.properties(BlockBehaviour.Properties::dynamicShape)
19941999
.tag(FHTags.Blocks.SCAFFOLDING.tag, BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.MINEABLE_WITH_AXE, BlockTags.CLIMBABLE, AllTags.AllBlockTags.WRENCH_PICKUP.tag)
19952000
.blockstate(existed())
1996-
.simpleItem()
2001+
.item(FHScaffoldingBlockItem::new)
2002+
.build()
19972003
.register();
19982004

19992005
public static final BlockEntry<WarehouseStorageRackBlock> WAREHOUSE_STORAGE_RACK = REGISTRATE.block("warehouse_storage_rack", WarehouseStorageRackBlock::new)

src/main/java/com/teammoeg/frostedheart/content/decoration/FHScaffoldingBlock.java

Lines changed: 15 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
package com.teammoeg.frostedheart.content.decoration;
22

3-
import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem;
4-
import com.simibubi.create.foundation.placement.IPlacementHelper;
5-
import com.simibubi.create.foundation.placement.PlacementHelpers;
6-
import com.simibubi.create.foundation.placement.PlacementOffset;
7-
import com.simibubi.create.infrastructure.config.AllConfigs;
83
import com.teammoeg.chorda.block.CBlock;
94
import com.teammoeg.chorda.util.struct.FastEnumMap;
105
import com.teammoeg.frostedheart.bootstrap.reference.FHTags;
116
import net.minecraft.core.BlockPos;
127
import net.minecraft.core.Direction;
13-
import net.minecraft.sounds.SoundEvents;
14-
import net.minecraft.sounds.SoundSource;
15-
import net.minecraft.world.InteractionHand;
16-
import net.minecraft.world.InteractionResult;
17-
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
18-
import net.minecraft.world.entity.player.Player;
8+
import net.minecraft.world.entity.LivingEntity;
199
import net.minecraft.world.item.BlockItem;
20-
import net.minecraft.world.item.ItemStack;
2110
import net.minecraft.world.item.context.BlockPlaceContext;
2211
import net.minecraft.world.level.BlockGetter;
23-
import net.minecraft.world.level.Level;
2412
import net.minecraft.world.level.LevelAccessor;
2513
import net.minecraft.world.level.block.Block;
2614
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
@@ -30,19 +18,17 @@
3018
import net.minecraft.world.level.block.state.properties.BooleanProperty;
3119
import net.minecraft.world.level.material.FluidState;
3220
import net.minecraft.world.level.material.Fluids;
33-
import net.minecraft.world.phys.BlockHitResult;
3421
import net.minecraft.world.phys.shapes.CollisionContext;
22+
import net.minecraft.world.phys.shapes.EntityCollisionContext;
3523
import net.minecraft.world.phys.shapes.Shapes;
3624
import net.minecraft.world.phys.shapes.VoxelShape;
37-
import net.minecraftforge.common.ForgeMod;
3825
import net.minecraftforge.registries.ForgeRegistries;
3926
import org.jetbrains.annotations.NotNull;
4027
import org.jetbrains.annotations.Nullable;
4128

4229
import java.util.ArrayList;
4330
import java.util.List;
4431
import java.util.concurrent.ConcurrentHashMap;
45-
import java.util.function.Predicate;
4632

4733
public class FHScaffoldingBlock extends CBlock implements SimpleWaterloggedBlock {
4834
public static final BooleanProperty SURFACE = BooleanProperty.create("surface");
@@ -69,8 +55,6 @@ public class FHScaffoldingBlock extends CBlock implements SimpleWaterloggedBlock
6955

7056
private static final ConcurrentHashMap<BlockState, VoxelShape> shapeCache = new ConcurrentHashMap<>();
7157

72-
public static final int PLACEMENT_HELPER_ID = PlacementHelpers.register(new ScaffoldingPlacementHelper());
73-
7458
public FHScaffoldingBlock(Properties blockProps) {
7559
super(blockProps);
7660
registerDefaultState(stateDefinition.any()
@@ -99,7 +83,7 @@ protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockSt
9983

10084
@Override
10185
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
102-
return isScaffolding(pState) ? Shapes.block() : shapeCache.computeIfAbsent(pState, this::computeShape);
86+
return isHoldingScaffolding(pState, pLevel, pPos, pContext) ? Shapes.block() : shapeCache.computeIfAbsent(pState, this::computeShape);
10387
}
10488

10589
private VoxelShape computeShape(BlockState state) {
@@ -138,24 +122,6 @@ public FluidState getFluidState(BlockState pState) {
138122
return pState.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(pState);
139123
}
140124

141-
@Override
142-
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, BlockHitResult pHit) {
143-
var heldItem = pPlayer.getItemInHand(pHand);
144-
145-
if (heldItem.is(FHTags.forgeTag(ForgeRegistries.ITEMS, "rods"))) {
146-
pLevel.setBlock(pPos, pState.setValue(HANDRAIL, !pState.getValue(HANDRAIL)), 2);
147-
pLevel.playSound((Player)null, pPos, SoundEvents.COPPER_PLACE, SoundSource.BLOCKS, 1.0F, 0.8F + pLevel.random.nextFloat() * 0.4F);
148-
return InteractionResult.SUCCESS;
149-
}
150-
151-
IPlacementHelper helper = PlacementHelpers.get(PLACEMENT_HELPER_ID);
152-
if (helper.matchesItem(heldItem))
153-
return helper.getOffset(pPlayer, pLevel, pState, pPos, pHit)
154-
.placeInWorld(pLevel, (BlockItem) heldItem.getItem(), pPlayer, pHand, pHit);
155-
156-
return super.use(pState, pLevel, pPos, pPlayer, pHand, pHit);
157-
}
158-
159125
@Override
160126
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, LevelAccessor pLevel, BlockPos pPos, BlockPos pNeighborPos) {
161127
if (pState.getValue(BlockStateProperties.WATERLOGGED)) {
@@ -217,78 +183,23 @@ public static boolean isScaffolding(BlockState state) {
217183
return state.is(FHTags.Blocks.SCAFFOLDING.get());
218184
}
219185

186+
public static boolean isHoldingScaffolding(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
187+
if (context instanceof EntityCollisionContext ecc) {
188+
if (ecc.getEntity() instanceof LivingEntity entity && entity.getMainHandItem().getItem() instanceof BlockItem bi) {
189+
return isScaffolding(bi.getBlock().defaultBlockState());
190+
}
191+
return false;
192+
}
193+
194+
var tags = ForgeRegistries.BLOCKS.tags();
195+
return tags != null && tags.getTag(FHTags.Blocks.SCAFFOLDING.tag).stream().anyMatch(b -> context.isHoldingItem(b.asItem()));
196+
}
197+
220198
public static FastEnumMap<Direction, BlockPos> getNeighbors(BlockPos pos) {
221199
FastEnumMap<Direction, BlockPos> map = new FastEnumMap<>(Direction.values());
222200
for (Direction dir : Direction.values()) {
223201
map.put(dir, pos.relative(dir));
224202
}
225203
return map;
226204
}
227-
228-
public static class ScaffoldingPlacementHelper implements IPlacementHelper {
229-
230-
@Override
231-
public Predicate<ItemStack> getItemPredicate() {
232-
return i -> i.getItem() instanceof BlockItem
233-
&& ((BlockItem) i.getItem()).getBlock() instanceof FHScaffoldingBlock;
234-
}
235-
236-
@Override
237-
public Predicate<BlockState> getStatePredicate() {
238-
return FHScaffoldingBlock::isScaffolding;
239-
}
240-
241-
private boolean canExtendToward(BlockState state, Direction side) {
242-
return getStatePredicate().test(state) && side.getAxis() == Direction.Axis.Y;
243-
}
244-
245-
private int attachedBlocks(Level world, BlockPos pos, Direction direction) {
246-
BlockPos checkPos = pos.relative(direction);
247-
int count = 0;
248-
while (getStatePredicate().test(world.getBlockState(checkPos))) {
249-
count++;
250-
checkPos = checkPos.relative(direction);
251-
}
252-
return count;
253-
}
254-
255-
@Override
256-
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, BlockHitResult ray) {
257-
List<Direction> directions;
258-
259-
if (player != null && ray.getDirection() == Direction.UP) {
260-
Direction facing = player.getDirection();
261-
directions = List.of(facing);
262-
} else {
263-
directions = IPlacementHelper.orderedByDistance(pos, ray.getLocation(),
264-
dir -> canExtendToward(state, dir));
265-
}
266-
267-
int range = AllConfigs.server().equipment.placementAssistRange.get();
268-
if (player != null) {
269-
AttributeInstance reach = player.getAttribute(ForgeMod.BLOCK_REACH.get());
270-
if (reach != null && reach.hasModifier(ExtendoGripItem.singleRangeAttributeModifier))
271-
range += 4;
272-
}
273-
274-
for (Direction dir : directions) {
275-
int poles = attachedBlocks(world, pos, dir);
276-
if (poles >= range)
277-
continue;
278-
279-
BlockPos newPos = pos.relative(dir, poles + 1);
280-
int newY = newPos.getY();
281-
if (newY <= world.getMinBuildHeight() || newY >= world.getMaxBuildHeight())
282-
continue;
283-
BlockState newState = world.getBlockState(newPos);
284-
if (!newState.canBeReplaced())
285-
continue;
286-
287-
return PlacementOffset.success(newPos,
288-
bState -> calcState(bState, newPos, world));
289-
}
290-
291-
return PlacementOffset.fail();
292-
}
293-
}
294205
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.teammoeg.frostedheart.content.decoration;
2+
3+
import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem;
4+
import com.simibubi.create.foundation.mixin.accessor.UseOnContextAccessor;
5+
import com.simibubi.create.foundation.placement.IPlacementHelper;
6+
import com.simibubi.create.foundation.placement.PlacementHelpers;
7+
import com.simibubi.create.foundation.placement.PlacementOffset;
8+
import com.simibubi.create.infrastructure.config.AllConfigs;
9+
import com.teammoeg.frostedheart.item.FHBlockItem;
10+
import net.minecraft.core.BlockPos;
11+
import net.minecraft.core.Direction;
12+
import net.minecraft.world.InteractionResult;
13+
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
14+
import net.minecraft.world.entity.player.Player;
15+
import net.minecraft.world.item.BlockItem;
16+
import net.minecraft.world.item.ItemStack;
17+
import net.minecraft.world.item.context.UseOnContext;
18+
import net.minecraft.world.level.Level;
19+
import net.minecraft.world.level.block.Block;
20+
import net.minecraft.world.level.block.state.BlockState;
21+
import net.minecraft.world.phys.BlockHitResult;
22+
import net.minecraftforge.common.ForgeMod;
23+
24+
import javax.annotation.Nullable;
25+
import java.util.List;
26+
import java.util.function.Predicate;
27+
28+
public class FHScaffoldingBlockItem extends FHBlockItem {
29+
30+
public FHScaffoldingBlockItem(Block pBlock, Properties pProperties) {
31+
super(pBlock, pProperties);
32+
}
33+
34+
@Override
35+
public InteractionResult onItemUseFirst(ItemStack stack, UseOnContext context) {
36+
var result = helperPlace(stack, context, PLACEMENT_HELPER_ID);
37+
if (result != null) return result;
38+
39+
return super.onItemUseFirst(stack, context);
40+
}
41+
42+
@Nullable
43+
public static InteractionResult helperPlace(ItemStack stack, UseOnContext context, int helperId) {
44+
var player = context.getPlayer();
45+
if (player != null && !player.isShiftKeyDown()) {
46+
var level = context.getLevel();
47+
var pos = context.getClickedPos();
48+
var state = level.getBlockState(pos);
49+
IPlacementHelper helper = PlacementHelpers.get(helperId);
50+
if (helper.matchesItem(stack) && helper.matchesState(state)) {
51+
var hit = ((UseOnContextAccessor)context).create$getHitResult();
52+
var result = helper.getOffset(player, level, state, pos, hit)
53+
.placeInWorld(level, (BlockItem) stack.getItem(), player, context.getHand(), hit);
54+
if (result == InteractionResult.PASS) {
55+
return InteractionResult.FAIL;
56+
}
57+
return result;
58+
}
59+
}
60+
61+
return null;
62+
}
63+
64+
public static final int PLACEMENT_HELPER_ID = PlacementHelpers.register(new ScaffoldingPlacementHelper());
65+
66+
public static class ScaffoldingPlacementHelper implements IPlacementHelper {
67+
68+
@Override
69+
public Predicate<ItemStack> getItemPredicate() {
70+
return i -> i.getItem() instanceof BlockItem
71+
&& ((BlockItem) i.getItem()).getBlock() instanceof FHScaffoldingBlock;
72+
}
73+
74+
@Override
75+
public Predicate<BlockState> getStatePredicate() {
76+
return FHScaffoldingBlock::isScaffolding;
77+
}
78+
79+
private boolean canExtendToward(BlockState state, Direction side) {
80+
return getStatePredicate().test(state) && side.getAxis() == Direction.Axis.Y;
81+
}
82+
83+
private int attachedBlocks(Level world, BlockPos pos, Direction direction) {
84+
BlockPos checkPos = pos.relative(direction);
85+
int count = 0;
86+
while (getStatePredicate().test(world.getBlockState(checkPos))) {
87+
count++;
88+
checkPos = checkPos.relative(direction);
89+
}
90+
return count;
91+
}
92+
93+
@Override
94+
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, BlockHitResult ray) {
95+
List<Direction> directions;
96+
97+
if (player != null && ray.getDirection() == Direction.UP) {
98+
Direction facing = player.getDirection();
99+
directions = List.of(facing);
100+
} else {
101+
directions = IPlacementHelper.orderedByDistance(pos, ray.getLocation(),
102+
dir -> canExtendToward(state, dir));
103+
}
104+
105+
int range = AllConfigs.server().equipment.placementAssistRange.get();
106+
if (player != null) {
107+
AttributeInstance reach = player.getAttribute(ForgeMod.BLOCK_REACH.get());
108+
if (reach != null && reach.hasModifier(ExtendoGripItem.singleRangeAttributeModifier))
109+
range += 4;
110+
}
111+
112+
for (Direction dir : directions) {
113+
int poles = attachedBlocks(world, pos, dir);
114+
if (poles >= range)
115+
continue;
116+
117+
BlockPos newPos = pos.relative(dir, poles + 1);
118+
int newY = newPos.getY();
119+
if (newY <= world.getMinBuildHeight() || newY >= world.getMaxBuildHeight())
120+
continue;
121+
BlockState newState = world.getBlockState(newPos);
122+
if (!newState.canBeReplaced())
123+
continue;
124+
125+
return PlacementOffset.success(newPos,
126+
bState -> FHScaffoldingBlock.calcState(bState, newPos, world));
127+
}
128+
129+
return PlacementOffset.fail();
130+
}
131+
}
132+
}

0 commit comments

Comments
 (0)