Clickable doors

- Fixed item dupe when interacting with moving deployers
- Added movement interaction behaviours for doors and trapdoors
This commit is contained in:
simibubi 2021-10-21 20:46:26 +02:00
parent a03025a0a3
commit dca6cc0bff
8 changed files with 245 additions and 103 deletions

View file

@ -1,48 +1,66 @@
package com.simibubi.create; package com.simibubi.create;
import java.util.HashMap;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.contraptions.components.deployer.DeployerMovingInteraction; import com.simibubi.create.content.contraptions.components.deployer.DeployerMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.function.Supplier;
public class AllInteractionBehaviours { public class AllInteractionBehaviours {
private static final HashMap<ResourceLocation, Supplier<MovingInteractionBehaviour>> INTERACT_BEHAVIOURS = new HashMap<>(); private static final HashMap<ResourceLocation, Supplier<MovingInteractionBehaviour>> INTERACT_BEHAVIOURS =
new HashMap<>();
public static void addInteractionBehaviour (ResourceLocation loc, Supplier<MovingInteractionBehaviour> behaviour) { public static void addInteractionBehaviour(ResourceLocation loc, Supplier<MovingInteractionBehaviour> behaviour) {
if (INTERACT_BEHAVIOURS.containsKey(loc)) { if (INTERACT_BEHAVIOURS.containsKey(loc))
Create.LOGGER.warn("Interaction behaviour for " + loc.toString() + " was overridden"); Create.LOGGER.warn("Interaction behaviour for " + loc.toString() + " was overridden");
}
INTERACT_BEHAVIOURS.put(loc, behaviour); INTERACT_BEHAVIOURS.put(loc, behaviour);
} }
public static void addInteractionBehavioiur (Block block, Supplier<MovingInteractionBehaviour> behaviour) { public static void addInteractionBehaviour(Block block, Supplier<MovingInteractionBehaviour> behaviour) {
addInteractionBehaviour(block.getRegistryName(), behaviour); addInteractionBehaviour(block.getRegistryName(), behaviour);
} }
@Nullable @Nullable
public static MovingInteractionBehaviour of (ResourceLocation loc) { public static MovingInteractionBehaviour of(ResourceLocation loc) {
return (INTERACT_BEHAVIOURS.get(loc) == null) ? null : INTERACT_BEHAVIOURS.get(loc).get(); return (INTERACT_BEHAVIOURS.get(loc) == null) ? null
: INTERACT_BEHAVIOURS.get(loc)
.get();
} }
@Nullable @Nullable
public static MovingInteractionBehaviour of (Block block) { public static MovingInteractionBehaviour of(Block block) {
return of(block.getRegistryName()); return of(block.getRegistryName());
} }
public static boolean contains (Block block) { public static boolean contains(Block block) {
return INTERACT_BEHAVIOURS.containsKey(block.getRegistryName()); return INTERACT_BEHAVIOURS.containsKey(block.getRegistryName());
} }
static void register () { static void register() {
addInteractionBehaviour(Blocks.LEVER.getRegistryName(), LeverMovingInteraction::new); addInteractionBehaviour(Blocks.LEVER.getRegistryName(), LeverMovingInteraction::new);
addInteractionBehaviour(AllBlocks.DEPLOYER.getId(), DeployerMovingInteraction::new); addInteractionBehaviour(AllBlocks.DEPLOYER.getId(), DeployerMovingInteraction::new);
// TODO: Scan registry for instanceof (-> modded door support)
for (Block trapdoor : ImmutableList.of(Blocks.ACACIA_TRAPDOOR, Blocks.OAK_TRAPDOOR, Blocks.DARK_OAK_TRAPDOOR,
Blocks.SPRUCE_TRAPDOOR, Blocks.JUNGLE_TRAPDOOR, Blocks.BIRCH_TRAPDOOR, Blocks.WARPED_TRAPDOOR,
Blocks.CRIMSON_TRAPDOOR)) {
addInteractionBehaviour(trapdoor.getRegistryName(), TrapdoorMovingInteraction::new);
}
for (Block door : ImmutableList.of(Blocks.ACACIA_DOOR, Blocks.OAK_DOOR, Blocks.DARK_OAK_DOOR,
Blocks.SPRUCE_DOOR, Blocks.JUNGLE_DOOR, Blocks.BIRCH_DOOR, Blocks.WARPED_DOOR, Blocks.CRIMSON_DOOR)) {
addInteractionBehaviour(door.getRegistryName(), DoorMovingInteraction::new);
}
} }
} }

View file

@ -1,73 +1,77 @@
package com.simibubi.create.content.contraptions.components.deployer; package com.simibubi.create.content.contraptions.components.deployer;
import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import org.apache.commons.lang3.tuple.MutablePair;
public class DeployerMovingInteraction extends MovingInteractionBehaviour { public class DeployerMovingInteraction extends MovingInteractionBehaviour {
@Override @Override
public boolean handlePlayerInteraction (PlayerEntity player, Hand activeHand, BlockPos localPos, AbstractContraptionEntity contraptionEntity) { public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos,
BlockInfo info = contraptionEntity.getContraption().getBlocks().get(localPos); AbstractContraptionEntity contraptionEntity) {
if (info == null) return false; BlockInfo info = contraptionEntity.getContraption()
.getBlocks()
.get(localPos);
if (info == null)
return false;
MovementContext ctx = null; MovementContext ctx = null;
int index = -1; int index = -1;
for (MutablePair<BlockInfo, MovementContext> pair : contraptionEntity.getContraption().getActors()) { for (MutablePair<BlockInfo, MovementContext> pair : contraptionEntity.getContraption()
.getActors()) {
if (info.equals(pair.left)) { if (info.equals(pair.left)) {
ctx = pair.right; ctx = pair.right;
index = contraptionEntity.getContraption().getActors().indexOf(pair); index = contraptionEntity.getContraption()
.getActors()
.indexOf(pair);
break; break;
} }
} }
if (ctx == null) return false; if (ctx == null)
return false;
ItemStack heldStack = player.getItemInHand(activeHand); ItemStack heldStack = player.getItemInHand(activeHand);
// Create.LOGGER.info("<-CTX: " + ctx.data.toString()); if (heldStack.getItem()
if (heldStack.getItem().equals(AllItems.WRENCH.get())) { .equals(AllItems.WRENCH.get())) {
DeployerTileEntity.Mode mode = NBTHelper.readEnum(ctx.tileData, "Mode", DeployerTileEntity.Mode.class); DeployerTileEntity.Mode mode = NBTHelper.readEnum(ctx.tileData, "Mode", DeployerTileEntity.Mode.class);
NBTHelper.writeEnum(ctx.tileData, "Mode", NBTHelper.writeEnum(ctx.tileData, "Mode",
mode==DeployerTileEntity.Mode.PUNCH ? DeployerTileEntity.Mode.USE : DeployerTileEntity.Mode.PUNCH mode == DeployerTileEntity.Mode.PUNCH ? DeployerTileEntity.Mode.USE : DeployerTileEntity.Mode.PUNCH);
);
// Create.LOGGER.info("Changed mode");
} else { } else {
if (ctx.world.isClientSide) return true; // we'll try again on the server side if (ctx.world.isClientSide)
return true; // we'll try again on the server side
DeployerFakePlayer fake = null; DeployerFakePlayer fake = null;
if ( !(ctx.temporaryData instanceof DeployerFakePlayer) && ctx.world instanceof ServerWorld) {
ctx.temporaryData = new DeployerFakePlayer((ServerWorld) ctx.world); if (!(ctx.temporaryData instanceof DeployerFakePlayer) && ctx.world instanceof ServerWorld) {
} else { DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerWorld) ctx.world);
fake = (DeployerFakePlayer)ctx.temporaryData; deployerFakePlayer.inventory.load(ctx.tileData.getList("Inventory", Constants.NBT.TAG_COMPOUND));
} ctx.temporaryData = fake = deployerFakePlayer;
if (fake == null) return false; ctx.tileData.remove("Inventory");
fake.inventory.load(ctx.tileData.getList("Inventory", Constants.NBT.TAG_COMPOUND)); } else
if (ctx.data.contains("HeldItem")) { fake = (DeployerFakePlayer) ctx.temporaryData;
player.setItemInHand(activeHand, ItemStack.of(ctx.data.getCompound("HeldItem")));
fake.setItemInHand(Hand.MAIN_HAND, heldStack); if (fake == null)
ctx.tileData.put("HeldItem", heldStack.serializeNBT()); return false;
ctx.data.put("HeldItem", heldStack.serializeNBT());
} ItemStack deployerItem = fake.getMainHandItem();
ctx.tileData.remove("Inventory"); player.setItemInHand(activeHand, deployerItem.copy());
ctx.temporaryData = fake; fake.setItemInHand(Hand.MAIN_HAND, heldStack.copy());
// Create.LOGGER.info("Swapped items"); ctx.tileData.put("HeldItem", heldStack.serializeNBT());
ctx.data.put("HeldItem", heldStack.serializeNBT());
} }
if (index >= 0) { if (index >= 0)
// Create.LOGGER.info("->CTX: " + ctx.data.toString());
setContraptionActorData(contraptionEntity, index, info, ctx); setContraptionActorData(contraptionEntity, index, info, ctx);
}
return true; return true;
} }
} }

View file

@ -257,7 +257,8 @@ public abstract class Contraption {
.stream() .stream()
.map(MountedStorage::getItemHandler) .map(MountedStorage::getItemHandler)
.collect(Collectors.toList()); .collect(Collectors.toList());
inventory = new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); inventory =
new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
List<IFluidHandler> fluidHandlers = fluidStorage.values() List<IFluidHandler> fluidHandlers = fluidStorage.values()
.stream() .stream()
@ -320,7 +321,7 @@ public abstract class Contraption {
if (!movementAllowed(state, world, pos)) if (!movementAllowed(state, world, pos))
throw AssemblyException.unmovableBlock(pos, state); throw AssemblyException.unmovableBlock(pos, state);
if (state.getBlock() instanceof AbstractChassisBlock if (state.getBlock() instanceof AbstractChassisBlock
&& !moveChassis(world, pos, forcedDirection, frontier, visited)) && !moveChassis(world, pos, forcedDirection, frontier, visited))
return false; return false;
if (AllBlocks.ADJUSTABLE_CRATE.has(state)) if (AllBlocks.ADJUSTABLE_CRATE.has(state))
@ -339,7 +340,7 @@ public abstract class Contraption {
Direction offset = state.getValue(StickerBlock.FACING); Direction offset = state.getValue(StickerBlock.FACING);
BlockPos attached = pos.relative(offset); BlockPos attached = pos.relative(offset);
if (!visited.contains(attached) if (!visited.contains(attached)
&& !BlockMovementChecks.isNotSupportive(world.getBlockState(attached), offset.getOpposite())) && !BlockMovementChecks.isNotSupportive(world.getBlockState(attached), offset.getOpposite()))
frontier.add(attached); frontier.add(attached);
} }
@ -391,12 +392,12 @@ public abstract class Contraption {
boolean wasVisited = visited.contains(offsetPos); boolean wasVisited = visited.contains(offsetPos);
boolean faceHasGlue = superglue.containsKey(offset); boolean faceHasGlue = superglue.containsKey(offset);
boolean blockAttachedTowardsFace = boolean blockAttachedTowardsFace =
BlockMovementChecks.isBlockAttachedTowards(blockState, world, offsetPos, offset.getOpposite()); BlockMovementChecks.isBlockAttachedTowards(blockState, world, offsetPos, offset.getOpposite());
boolean brittle = BlockMovementChecks.isBrittle(blockState); boolean brittle = BlockMovementChecks.isBrittle(blockState);
boolean canStick = !brittle && state.canStickTo(blockState) && blockState.canStickTo(state); boolean canStick = !brittle && state.canStickTo(blockState) && blockState.canStickTo(state);
if (canStick) { if (canStick) {
if (state.getPistonPushReaction() == PushReaction.PUSH_ONLY if (state.getPistonPushReaction() == PushReaction.PUSH_ONLY
|| blockState.getPistonPushReaction() == PushReaction.PUSH_ONLY) { || blockState.getPistonPushReaction() == PushReaction.PUSH_ONLY) {
canStick = false; canStick = false;
} }
if (BlockMovementChecks.isNotSupportive(state, offset)) { if (BlockMovementChecks.isNotSupportive(state, offset)) {
@ -408,7 +409,7 @@ public abstract class Contraption {
} }
if (!wasVisited && (canStick || blockAttachedTowardsFace || faceHasGlue if (!wasVisited && (canStick || blockAttachedTowardsFace || faceHasGlue
|| (offset == forcedDirection && !BlockMovementChecks.isNotSupportive(state, forcedDirection)))) || (offset == forcedDirection && !BlockMovementChecks.isNotSupportive(state, forcedDirection))))
frontier.add(offsetPos); frontier.add(offsetPos);
if (faceHasGlue) if (faceHasGlue)
addGlue(superglue.get(offset)); addGlue(superglue.get(offset));
@ -432,7 +433,8 @@ public abstract class Contraption {
frontier.add(offset); frontier.add(offset);
if (blockState.getBlock() instanceof MechanicalPistonBlock) { if (blockState.getBlock() instanceof MechanicalPistonBlock) {
Direction pistonFacing = blockState.getValue(MechanicalPistonBlock.FACING); Direction pistonFacing = blockState.getValue(MechanicalPistonBlock.FACING);
if (pistonFacing == direction && blockState.getValue(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) if (pistonFacing == direction
&& blockState.getValue(MechanicalPistonBlock.STATE) == PistonState.EXTENDED)
frontier.add(offset); frontier.add(offset);
} }
} }
@ -492,7 +494,8 @@ public abstract class Contraption {
if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState) if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState)
&& offsetState.getValue(GantryShaftBlock.FACING) == facing) && offsetState.getValue(GantryShaftBlock.FACING) == facing)
frontier.add(offset); frontier.add(offset);
else if (AllBlocks.GANTRY_CARRIAGE.has(offsetState) && offsetState.getValue(GantryCarriageBlock.FACING) == d) else if (AllBlocks.GANTRY_CARRIAGE.has(offsetState)
&& offsetState.getValue(GantryCarriageBlock.FACING) == d)
frontier.add(offset); frontier.add(offset);
} }
} }
@ -700,8 +703,8 @@ public abstract class Contraption {
}); });
superglue.clear(); superglue.clear();
NBTHelper.iterateCompoundList(nbt.getList("Superglue", NBT.TAG_COMPOUND), c -> superglue NBTHelper.iterateCompoundList(nbt.getList("Superglue", NBT.TAG_COMPOUND), c -> superglue.add(
.add(Pair.of(NBTUtil.readBlockPos(c.getCompound("Pos")), Direction.from3DDataValue(c.getByte("Direction"))))); Pair.of(NBTUtil.readBlockPos(c.getCompound("Pos")), Direction.from3DDataValue(c.getByte("Direction")))));
seats.clear(); seats.clear();
NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND), c -> seats.add(NBTUtil.readBlockPos(c))); NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND), c -> seats.add(NBTUtil.readBlockPos(c)));
@ -725,7 +728,9 @@ public abstract class Contraption {
interactors.clear(); interactors.clear();
NBTHelper.iterateCompoundList(nbt.getList("Interactors", NBT.TAG_COMPOUND), c -> { NBTHelper.iterateCompoundList(nbt.getList("Interactors", NBT.TAG_COMPOUND), c -> {
BlockPos pos = NBTUtil.readBlockPos(c.getCompound("Pos")); BlockPos pos = NBTUtil.readBlockPos(c.getCompound("Pos"));
interactors.put(pos, AllInteractionBehaviours.of(getBlocks().get(pos).state.getBlock())); MovingInteractionBehaviour behaviour = AllInteractionBehaviours.of(getBlocks().get(pos).state.getBlock());
if (behaviour != null)
interactors.put(pos, behaviour);
}); });
if (spawnData) if (spawnData)
@ -960,7 +965,7 @@ public abstract class Contraption {
continue; continue;
BlockPos add = block.pos.offset(anchor) BlockPos add = block.pos.offset(anchor)
.offset(offset); .offset(offset);
if (customBlockRemoval(world, add, block.state)) if (customBlockRemoval(world, add, block.state))
continue; continue;
BlockState oldState = world.getBlockState(add); BlockState oldState = world.getBlockState(add);
@ -991,14 +996,18 @@ public abstract class Contraption {
// remove it again, so to prevent an error from being logged by double-removal we add the POI data back now // remove it again, so to prevent an error from being logged by double-removal we add the POI data back now
// (code copied from ServerWorld.onBlockStateChange) // (code copied from ServerWorld.onBlockStateChange)
ServerWorld serverWorld = (ServerWorld) world; ServerWorld serverWorld = (ServerWorld) world;
PointOfInterestType.forState(block.state).ifPresent(poiType -> { PointOfInterestType.forState(block.state)
world.getServer().execute(() -> { .ifPresent(poiType -> {
serverWorld.getPoiManager().add(add, poiType); world.getServer()
DebugPacketSender.sendPoiAddedPacket(serverWorld, add); .execute(() -> {
serverWorld.getPoiManager()
.add(add, poiType);
DebugPacketSender.sendPoiAddedPacket(serverWorld, add);
});
}); });
});
world.markAndNotifyBlock(add, world.getChunkAt(add), block.state, Blocks.AIR.defaultBlockState(), flags, 512); world.markAndNotifyBlock(add, world.getChunkAt(add), block.state, Blocks.AIR.defaultBlockState(), flags,
512);
block.state.updateIndirectNeighbourShapes(world, add, flags & -2); block.state.updateIndirectNeighbourShapes(world, add, flags & -2);
} }
} }
@ -1017,8 +1026,8 @@ public abstract class Contraption {
if (nonBrittles) if (nonBrittles)
for (Direction face : Iterate.directions) for (Direction face : Iterate.directions)
state = state.updateShape(face, world.getBlockState(targetPos.relative(face)), world, state = state.updateShape(face, world.getBlockState(targetPos.relative(face)), world, targetPos,
targetPos, targetPos.relative(face)); targetPos.relative(face));
BlockState blockState = world.getBlockState(targetPos); BlockState blockState = world.getBlockState(targetPos);
if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos)
@ -1215,7 +1224,9 @@ public abstract class Contraption {
return actors; return actors;
} }
public Map<BlockPos, MovingInteractionBehaviour> getInteractors () { return interactors; } public Map<BlockPos, MovingInteractionBehaviour> getInteractors() {
return interactors;
}
public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) { public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) {
MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos); MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos);
@ -1228,6 +1239,11 @@ public abstract class Contraption {
return new EmptyLighter(this); return new EmptyLighter(this);
} }
public void invalidateColliders() {
simplifiedEntityColliders = Optional.empty();
gatherBBsOffThread();
}
private void gatherBBsOffThread() { private void gatherBBsOffThread() {
getContraptionWorld(); getContraptionWorld();
simplifiedEntityColliderProvider = CompletableFuture.supplyAsync(() -> { simplifiedEntityColliderProvider = CompletableFuture.supplyAsync(() -> {
@ -1254,10 +1270,10 @@ public abstract class Contraption {
switch (axis) { switch (axis) {
case X: case X:
return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ); return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ);
case Y: case Y:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ); return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ);
case Z: case Z:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY); return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY);
} }
throw new IllegalStateException("Impossible axis"); throw new IllegalStateException("Impossible axis");

View file

@ -1,32 +1,33 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import org.apache.commons.lang3.tuple.MutablePair;
public abstract class MovingInteractionBehaviour { public abstract class MovingInteractionBehaviour {
public MovingInteractionBehaviour () { }
protected void setContraptionActorData (AbstractContraptionEntity contraptionEntity, int index, BlockInfo info, MovementContext ctx) { public MovingInteractionBehaviour() {}
protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, BlockInfo info,
MovementContext ctx) {
contraptionEntity.contraption.actors.remove(index); contraptionEntity.contraption.actors.remove(index);
contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx)); contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx));
// mark contraption to re-render because we changed actor data
ContraptionRenderDispatcher.invalidate(contraptionEntity.contraption); ContraptionRenderDispatcher.invalidate(contraptionEntity.contraption);
} }
protected void setContraptionBlockData (AbstractContraptionEntity contraptionEntity, BlockPos pos, BlockInfo info) { protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos, BlockInfo info) {
contraptionEntity.contraption.blocks.put(pos, info); contraptionEntity.contraption.blocks.put(pos, info);
// mark contraption to re-render because we changed block data
ContraptionRenderDispatcher.invalidate(contraptionEntity.contraption); ContraptionRenderDispatcher.invalidate(contraptionEntity.contraption);
} }
public boolean handlePlayerInteraction (PlayerEntity player, Hand activeHand, BlockPos localPos, AbstractContraptionEntity contraptionEntity) { public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos,
AbstractContraptionEntity contraptionEntity) {
return true; return true;
} }
} }

View file

@ -0,0 +1,38 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.block.BlockState;
import net.minecraft.block.DoorBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class DoorMovingInteraction extends SimpleBlockMovingInteraction {
@Override
protected BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, BlockState currentState) {
SoundEvent sound =
currentState.getValue(DoorBlock.OPEN) ? SoundEvents.WOODEN_DOOR_CLOSE : SoundEvents.WOODEN_DOOR_OPEN;
BlockPos otherPos = currentState.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? pos.above() : pos.below();
BlockInfo info = contraption.getBlocks()
.get(otherPos);
if (info.state.hasProperty(DoorBlock.OPEN))
setContraptionBlockData(contraption.entity, otherPos,
new BlockInfo(info.pos, info.state.cycle(DoorBlock.OPEN), info.nbt));
float pitch = player.level.random.nextFloat() * 0.1F + 0.9F;
playSound(player, sound, pitch);
return currentState.cycle(DoorBlock.OPEN);
}
@Override
protected boolean updateColliders() {
return true;
}
}

View file

@ -1,27 +1,19 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction; package com.simibubi.create.content.contraptions.components.structureMovement.interaction;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.LeverBlock;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class LeverMovingInteraction extends MovingInteractionBehaviour { public class LeverMovingInteraction extends SimpleBlockMovingInteraction {
@Override @Override
public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos, AbstractContraptionEntity contraptionEntity) { protected BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, BlockState currentState) {
BlockInfo info = contraptionEntity.getContraption().getBlocks().get(localPos); playSound(player, SoundEvents.LEVER_CLICK, currentState.getValue(LeverBlock.POWERED) ? 0.5f : 0.6f);
BlockState newState = info.state.cycle(BlockStateProperties.POWERED); return currentState.cycle(LeverBlock.POWERED);
setContraptionBlockData(contraptionEntity, localPos, new BlockInfo(info.pos, newState, info.nbt));
player.getCommandSenderWorld().playSound(
null, player.blockPosition(), SoundEvents.LEVER_CLICK, SoundCategory.BLOCKS, 0.3f,
newState.getValue(BlockStateProperties.POWERED) ? 0.6f : 0.5f
);
return true;
} }
} }

View file

@ -0,0 +1,45 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public abstract class SimpleBlockMovingInteraction extends MovingInteractionBehaviour {
@Override
public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos,
AbstractContraptionEntity contraptionEntity) {
Contraption contraption = contraptionEntity.getContraption();
BlockInfo info = contraption.getBlocks()
.get(localPos);
BlockState newState = handle(player, contraption, localPos, info.state);
if (info.state == newState)
return false;
setContraptionBlockData(contraptionEntity, localPos, new BlockInfo(info.pos, newState, info.nbt));
if (updateColliders())
contraption.invalidateColliders();
return true;
}
protected boolean updateColliders() {
return false;
}
protected void playSound(PlayerEntity player, SoundEvent sound, float pitch) {
player.level.playSound(player, player.blockPosition(), sound, SoundCategory.BLOCKS, 0.3f, pitch);
}
protected abstract BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos,
BlockState currentState);
}

View file

@ -0,0 +1,28 @@
package com.simibubi.create.content.contraptions.components.structureMovement.interaction;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.block.BlockState;
import net.minecraft.block.TrapDoorBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
public class TrapdoorMovingInteraction extends SimpleBlockMovingInteraction {
@Override
protected BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, BlockState currentState) {
SoundEvent sound = currentState.getValue(TrapDoorBlock.OPEN) ? SoundEvents.WOODEN_TRAPDOOR_CLOSE
: SoundEvents.WOODEN_TRAPDOOR_OPEN;
float pitch = player.level.random.nextFloat() * 0.1F + 0.9F;
playSound(player, sound, pitch);
return currentState.cycle(TrapDoorBlock.OPEN);
}
@Override
protected boolean updateColliders() {
return true;
}
}