mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-15 01:43:53 +01:00
Merge branch 'mc1.18/global-railways' of https://github.com/Creators-of-Create/Create-Concealed into mc1.18/global-railways
This commit is contained in:
commit
7199ebfb6b
4 changed files with 202 additions and 1 deletions
|
@ -5,6 +5,7 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock;
|
import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock;
|
||||||
|
@ -100,6 +101,13 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
|
||||||
return InteractionResult.SUCCESS;
|
return InteractionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AllItems.WRENCH.isIn(itemInHand) && !pPlayer.isSteppingCarefully()) {
|
||||||
|
if (GirderWrenchBehavior.handleClick(pLevel, pPos, pState, pHit))
|
||||||
|
return InteractionResult.sidedSuccess(pLevel.isClientSide);
|
||||||
|
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||||
if (helper.matchesItem(itemInHand))
|
if (helper.matchesItem(itemInHand))
|
||||||
return helper.getOffset(pPlayer, pLevel, pState, pPos, pHit)
|
return helper.getOffset(pPlayer, pLevel, pState, pPos, pHit)
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
package com.simibubi.create.content.curiosities.girder;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllItems;
|
||||||
|
import com.simibubi.create.CreateClient;
|
||||||
|
import com.simibubi.create.foundation.utility.Color;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
public class GirderWrenchBehavior {
|
||||||
|
|
||||||
|
public static void tick() {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
if (mc.player == null || mc.level == null || !(mc.hitResult instanceof BlockHitResult result))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ClientLevel world = mc.level;
|
||||||
|
BlockPos pos = result.getBlockPos();
|
||||||
|
Player player = mc.player;
|
||||||
|
ItemStack heldItem = player.getMainHandItem();
|
||||||
|
|
||||||
|
if (player.isSteppingCarefully())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!AllBlocks.METAL_GIRDER.has(world.getBlockState(pos)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!AllItems.WRENCH.isIn(heldItem))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Pair<Direction, Action> dirPair = getDirectionAndAction(result, world, pos);
|
||||||
|
if (dirPair == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vec3 center = VecHelper.getCenterOf(pos);
|
||||||
|
Vec3 edge = center.add(Vec3.atLowerCornerOf(dirPair.getFirst().getNormal()).scale(0.4));
|
||||||
|
Direction.Axis[] axes = Arrays.stream(Iterate.axes).filter(axis -> axis != dirPair.getFirst().getAxis()).toArray(Direction.Axis[]::new);
|
||||||
|
|
||||||
|
|
||||||
|
double normalMultiplier = dirPair.getSecond() == Action.PAIR ? 3 : 1;
|
||||||
|
Vec3 corner1 = edge
|
||||||
|
.add(Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axes[0], Direction.AxisDirection.POSITIVE).getNormal()).scale(0.3))
|
||||||
|
.add(Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axes[1], Direction.AxisDirection.POSITIVE).getNormal()).scale(0.3))
|
||||||
|
.add(Vec3.atLowerCornerOf(dirPair.getFirst().getNormal()).scale(0.1 * normalMultiplier));
|
||||||
|
|
||||||
|
normalMultiplier = dirPair.getSecond() == Action.HORIZONTAL ? 9 : 1;
|
||||||
|
Vec3 corner2 = edge
|
||||||
|
.add(Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axes[0], Direction.AxisDirection.NEGATIVE).getNormal()).scale(0.3))
|
||||||
|
.add(Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axes[1], Direction.AxisDirection.NEGATIVE).getNormal()).scale(0.3))
|
||||||
|
.add(Vec3.atLowerCornerOf(dirPair.getFirst().getOpposite().getNormal()).scale(0.1 * normalMultiplier));
|
||||||
|
|
||||||
|
CreateClient.OUTLINER.showAABB("girderWrench", new AABB(corner1, corner2))
|
||||||
|
.lineWidth(1 / 32f)
|
||||||
|
.colored(new Color(127, 127, 127));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Pair<Direction, Action> getDirectionAndAction(BlockHitResult result, Level world, BlockPos pos) {
|
||||||
|
List<Pair<Direction, Action>> validDirections = getValidDirections(world, pos);
|
||||||
|
|
||||||
|
if (validDirections.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<Direction> directions = IPlacementHelper.orderedByDistance(pos, result.getLocation(), validDirections.stream().map(Pair::getFirst).toList());
|
||||||
|
|
||||||
|
if (directions.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Direction dir = directions.get(0);
|
||||||
|
return validDirections.stream()
|
||||||
|
.filter(pair -> pair.getFirst() == dir)
|
||||||
|
.findFirst()
|
||||||
|
.orElseGet(() -> Pair.of(dir, Action.SINGLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Pair<Direction, Action>> getValidDirections(BlockGetter level, BlockPos pos) {
|
||||||
|
BlockState blockState = level.getBlockState(pos);
|
||||||
|
|
||||||
|
if (!AllBlocks.METAL_GIRDER.has(blockState))
|
||||||
|
return Collections.emptyList();
|
||||||
|
|
||||||
|
return Arrays.stream(Iterate.directions)
|
||||||
|
.<Pair<Direction, Action>>mapMulti((direction, consumer) -> {
|
||||||
|
BlockState other = level.getBlockState(pos.relative(direction));
|
||||||
|
|
||||||
|
// up and down
|
||||||
|
if (direction.getAxis() == Direction.Axis.Y) {
|
||||||
|
//no other girder in target dir
|
||||||
|
if (!AllBlocks.METAL_GIRDER.has(other)) {
|
||||||
|
if (!blockState.getValue(GirderBlock.X) ^ !blockState.getValue(GirderBlock.Z))
|
||||||
|
consumer.accept(Pair.of(direction, Action.SINGLE));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//this girder is a pole or cross
|
||||||
|
if (blockState.getValue(GirderBlock.X) == blockState.getValue(GirderBlock.Z))
|
||||||
|
return;
|
||||||
|
//other girder is a pole or cross
|
||||||
|
if (other.getValue(GirderBlock.X) == other.getValue(GirderBlock.Z))
|
||||||
|
return;
|
||||||
|
//toggle up/down connection for both
|
||||||
|
consumer.accept(Pair.of(direction, Action.PAIR));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AllBlocks.METAL_GIRDER.has(other))
|
||||||
|
consumer.accept(Pair.of(direction, Action.HORIZONTAL));
|
||||||
|
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean handleClick(Level level, BlockPos pos, BlockState state, BlockHitResult result) {
|
||||||
|
|
||||||
|
Pair<Direction, Action> dirPair = getDirectionAndAction(result, level, pos);
|
||||||
|
if (dirPair == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (level.isClientSide)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Direction dir = dirPair.getFirst();
|
||||||
|
|
||||||
|
BlockPos otherPos = pos.relative(dir);
|
||||||
|
BlockState other = level.getBlockState(otherPos);
|
||||||
|
|
||||||
|
if (dir == Direction.UP) {
|
||||||
|
level.setBlock(pos, state.cycle(GirderBlock.TOP), 2 | 16);
|
||||||
|
if (dirPair.getSecond() == Action.PAIR && AllBlocks.METAL_GIRDER.has(other)) {
|
||||||
|
level.setBlock(otherPos, other.cycle(GirderBlock.BOTTOM), 2 | 16);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir == Direction.DOWN) {
|
||||||
|
level.setBlock(pos, state.cycle(GirderBlock.BOTTOM), 2 | 16);
|
||||||
|
if (dirPair.getSecond() == Action.PAIR && AllBlocks.METAL_GIRDER.has(other)) {
|
||||||
|
level.setBlock(otherPos, other.cycle(GirderBlock.TOP), 2 | 16);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirPair.getSecond() == Action.HORIZONTAL) {
|
||||||
|
BooleanProperty property = dir.getAxis() == Direction.Axis.X ? GirderBlock.X : GirderBlock.Z;
|
||||||
|
level.setBlock(pos, state.cycle(property), 2 | 16);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Action {
|
||||||
|
SINGLE,
|
||||||
|
PAIR,
|
||||||
|
HORIZONTAL
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import com.simibubi.create.content.contraptions.components.turntable.TurntableHa
|
||||||
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
|
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler;
|
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler;
|
||||||
import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer;
|
import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer;
|
||||||
|
import com.simibubi.create.content.curiosities.girder.GirderWrenchBehavior;
|
||||||
import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient;
|
import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient;
|
||||||
import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
|
import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer;
|
||||||
import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
|
import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
|
||||||
|
@ -143,6 +144,7 @@ public class ClientEvents {
|
||||||
ScrollValueRenderer.tick();
|
ScrollValueRenderer.tick();
|
||||||
ChassisRangeDisplay.tick();
|
ChassisRangeDisplay.tick();
|
||||||
EdgeInteractionRenderer.tick();
|
EdgeInteractionRenderer.tick();
|
||||||
|
GirderWrenchBehavior.tick();
|
||||||
WorldshaperRenderHandler.tick();
|
WorldshaperRenderHandler.tick();
|
||||||
CouplingHandlerClient.tick();
|
CouplingHandlerClient.tick();
|
||||||
CouplingRenderer.tickDebugModeRenders();
|
CouplingRenderer.tickDebugModeRenders();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.foundation.utility.placement;
|
package com.simibubi.create.foundation.utility.placement;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -76,7 +77,7 @@ public interface IPlacementHelper {
|
||||||
* @param pos the position of the Block the player is looking at or clicked on
|
* @param pos the position of the Block the player is looking at or clicked on
|
||||||
* @param state the Blockstate of the Block that the player is looking at or clicked on
|
* @param state the Blockstate of the Block that the player is looking at or clicked on
|
||||||
* @param ray the exact raytrace result
|
* @param ray the exact raytrace result
|
||||||
* @param offset the PlacementOffset returned by {@link #getOffset(PlayerEntity, World, BlockState, BlockPos, BlockRayTraceResult)}<br>
|
* @param offset the PlacementOffset returned by {@link #getOffset(Player, Level, BlockState, BlockPos, BlockHitResult)}<br>
|
||||||
* the offset will always be successful if this method is called
|
* the offset will always be successful if this method is called
|
||||||
*/
|
*/
|
||||||
default void renderAt(BlockPos pos, BlockState state, BlockHitResult ray, PlacementOffset offset) {
|
default void renderAt(BlockPos pos, BlockState state, BlockHitResult ray, PlacementOffset offset) {
|
||||||
|
@ -147,6 +148,15 @@ public interface IPlacementHelper {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<Direction> orderedByDistance(BlockPos pos, Vec3 hit, Collection<Direction> directions) {
|
||||||
|
Vec3 centerToHit = hit.subtract(VecHelper.getCenterOf(pos));
|
||||||
|
return directions.stream()
|
||||||
|
.map(dir -> Pair.of(dir, Vec3.atLowerCornerOf(dir.getNormal()).distanceTo(centerToHit)))
|
||||||
|
.sorted(Comparator.comparingDouble(Pair::getSecond))
|
||||||
|
.map(Pair::getFirst)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
default boolean matchesItem(ItemStack item) {
|
default boolean matchesItem(ItemStack item) {
|
||||||
return getItemPredicate().test(item);
|
return getItemPredicate().test(item);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue