Order of Interact

- Fixed entity-specific interactions causing schedule interaction to be ignored
- Fixed viewport jittering when pressing movement keys while seated
- Fixed players dismounting trains/minecart contraptions causing them to be placed at incorrect locations
This commit is contained in:
simibubi 2022-09-23 23:04:49 +02:00
parent 4d4a959cfa
commit 1f06034b47
6 changed files with 97 additions and 44 deletions

View file

@ -33,6 +33,7 @@ import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.collision.Matrix3d;
import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor;
import com.simibubi.create.foundation.networking.AllPackets;
@ -181,16 +182,28 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
contraption.getSeatMapping()
.remove(passenger.getUUID());
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping()));
new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping(), passenger.getId()));
}
@Override
public Vec3 getDismountLocationForPassenger(LivingEntity pLivingEntity) {
Vec3 loc = super.getDismountLocationForPassenger(pLivingEntity);
CompoundTag data = pLivingEntity.getPersistentData();
public Vec3 getDismountLocationForPassenger(LivingEntity entityLiving) {
Vec3 position = super.getDismountLocationForPassenger(entityLiving);
CompoundTag data = entityLiving.getPersistentData();
if (!data.contains("ContraptionDismountLocation"))
return loc;
return VecHelper.readNBT(data.getList("ContraptionDismountLocation", Tag.TAG_DOUBLE));
return position;
position = VecHelper.readNBT(data.getList("ContraptionDismountLocation", Tag.TAG_DOUBLE));
data.remove("ContraptionDismountLocation");
entityLiving.setOnGround(false);
if (!data.contains("ContraptionMountLocation"))
return position;
Vec3 prevPosition = VecHelper.readNBT(data.getList("ContraptionMountLocation", Tag.TAG_DOUBLE));
data.remove("ContraptionMountLocation");
if (entityLiving instanceof Player player && !prevPosition.closerThan(position, 5000))
AllAdvancements.LONG_TRAVEL.awardTo(player);
return position;
}
@Override
@ -204,7 +217,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
transformedVector.y + SeatEntity.getCustomEntitySeatOffset(passenger) - 1 / 8f, transformedVector.z);
}
protected Vec3 getPassengerPosition(Entity passenger, float partialTicks) {
public Vec3 getPassengerPosition(Entity passenger, float partialTicks) {
UUID id = passenger.getUUID();
if (passenger instanceof OrientedContraptionEntity) {
BlockPos localPos = contraption.getBearingPosOf(id);

View file

@ -7,7 +7,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.WorldAttached;
@ -17,7 +16,6 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
@ -65,24 +63,18 @@ public class ContraptionHandler {
}
public static void entitiesWhoJustDismountedGetSentToTheRightLocation(LivingEntity entityLiving, Level world) {
if (world.isClientSide)
if (!world.isClientSide)
return;
CompoundTag data = entityLiving.getPersistentData();
if (!data.contains("ContraptionDismountLocation"))
return;
Vec3 position = VecHelper.readNBT(data.getList("ContraptionDismountLocation", Tag.TAG_DOUBLE));
if (entityLiving.getVehicle() == null)
entityLiving.teleportTo(position.x, position.y, position.z);
entityLiving.absMoveTo(position.x, position.y, position.z, entityLiving.getYRot(), entityLiving.getXRot());
data.remove("ContraptionDismountLocation");
entityLiving.setOnGround(false);
if (!data.contains("ContraptionMountLocation"))
return;
Vec3 prevPosition = VecHelper.readNBT(data.getList("ContraptionMountLocation", Tag.TAG_DOUBLE));
data.remove("ContraptionMountLocation");
if (entityLiving instanceof Player player && !prevPosition.closerThan(position, 5000))
AllAdvancements.LONG_TRAVEL.awardTo(player);
}
}

View file

@ -7,24 +7,33 @@ import java.util.function.Supplier;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.NetworkEvent.Context;
public class ContraptionSeatMappingPacket extends SimplePacketBase {
private Map<UUID, Integer> mapping;
private int entityID;
private int dismountedID;
public ContraptionSeatMappingPacket(int entityID, Map<UUID, Integer> mapping) {
this(entityID, mapping, -1);
}
public ContraptionSeatMappingPacket(int entityID, Map<UUID, Integer> mapping, int dismountedID) {
this.entityID = entityID;
this.mapping = mapping;
this.dismountedID = dismountedID;
}
public ContraptionSeatMappingPacket(FriendlyByteBuf buffer) {
entityID = buffer.readInt();
dismountedID = buffer.readInt();
mapping = new HashMap<>();
short size = buffer.readShort();
for (int i = 0; i < size; i++)
@ -34,6 +43,7 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase {
@Override
public void write(FriendlyByteBuf buffer) {
buffer.writeInt(entityID);
buffer.writeInt(dismountedID);
buffer.writeShort(mapping.size());
mapping.forEach((k, v) -> {
buffer.writeUUID(k);
@ -49,6 +59,17 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase {
if (!(entityByID instanceof AbstractContraptionEntity))
return;
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
if (dismountedID != -1) {
Entity dismountedByID = Minecraft.getInstance().level.getEntity(dismountedID);
if (Minecraft.getInstance().player != dismountedByID)
return;
Vec3 transformedVector = contraptionEntity.getPassengerPosition(dismountedByID, 1);
if (transformedVector != null)
dismountedByID.getPersistentData()
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
}
contraptionEntity.getContraption()
.setSeatMapping(mapping);
});

View file

@ -66,8 +66,7 @@ public class ScheduleItem extends Item implements MenuProvider {
return InteractionResultHolder.pass(heldItem);
}
@Override
public InteractionResult interactLivingEntity(ItemStack pStack, Player pPlayer, LivingEntity pInteractionTarget,
public InteractionResult handScheduleTo(ItemStack pStack, Player pPlayer, LivingEntity pInteractionTarget,
InteractionHand pUsedHand) {
InteractionResult pass = InteractionResult.PASS;
@ -123,6 +122,7 @@ public class ScheduleItem extends Item implements MenuProvider {
pStack.shrink(1);
pPlayer.setItemInHand(pUsedHand, pStack.isEmpty() ? ItemStack.EMPTY : pStack);
}
return InteractionResult.SUCCESS;
}

View file

@ -11,19 +11,20 @@ import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.animal.Wolf;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteract;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteractSpecific;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class ScheduleItemRetrieval {
public class ScheduleItemEntityInteraction {
@SubscribeEvent
public static void removeScheduleFromConductor(EntityInteract event) {
public static void interactWithConductor(EntityInteractSpecific event) {
Entity entity = event.getTarget();
Player player = event.getPlayer();
if (player == null || entity == null)
@ -34,16 +35,24 @@ public class ScheduleItemRetrieval {
Entity rootVehicle = entity.getRootVehicle();
if (!(rootVehicle instanceof CarriageContraptionEntity))
return;
if (!(entity instanceof LivingEntity living))
return;
if (player.getCooldowns()
.isOnCooldown(AllItems.SCHEDULE.get()))
return;
ItemStack itemStack = event.getItemStack();
if (AllItems.SCHEDULE.isIn(itemStack) && entity instanceof Wolf wolf) {
itemStack.getItem()
.interactLivingEntity(itemStack, player, wolf, event.getHand());
return;
if (itemStack.getItem()instanceof ScheduleItem si) {
InteractionResult result = si.handScheduleTo(itemStack, player, living, event.getHand());
if (result.consumesAction()) {
player.getCooldowns()
.addCooldown(AllItems.SCHEDULE.get(), 5);
event.setCancellationResult(result);
event.setCanceled(true);
return;
}
}
if (player.level.isClientSide)
return;
if (event.getHand() == InteractionHand.OFF_HAND)
return;
@ -68,31 +77,47 @@ public class ScheduleItemRetrieval {
if (directions == null)
return;
boolean onServer = !event.getWorld().isClientSide;
if (train.runtime.paused && !train.runtime.completed) {
train.runtime.paused = false;
AllSoundEvents.CONFIRM.playOnServer(player.level, player.blockPosition(), 1, 1);
player.displayClientMessage(Lang.translateDirect("schedule.continued"), true);
if (onServer) {
train.runtime.paused = false;
AllSoundEvents.CONFIRM.playOnServer(player.level, player.blockPosition(), 1, 1);
player.displayClientMessage(Lang.translateDirect("schedule.continued"), true);
}
player.getCooldowns()
.addCooldown(AllItems.SCHEDULE.get(), 5);
event.setCancellationResult(InteractionResult.SUCCESS);
event.setCanceled(true);
return;
}
ItemStack itemInHand = player.getItemInHand(event.getHand());
if (!itemInHand.isEmpty()) {
AllSoundEvents.DENY.playOnServer(player.level, player.blockPosition(), 1, 1);
player.displayClientMessage(Lang.translateDirect("schedule.remove_with_empty_hand"), true);
if (onServer) {
AllSoundEvents.DENY.playOnServer(player.level, player.blockPosition(), 1, 1);
player.displayClientMessage(Lang.translateDirect("schedule.remove_with_empty_hand"), true);
}
event.setCancellationResult(InteractionResult.SUCCESS);
event.setCanceled(true);
return;
}
AllSoundEvents.playItemPickup(player);
player.displayClientMessage(
Lang.translateDirect(
train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"),
true);
if (onServer) {
AllSoundEvents.playItemPickup(player);
player.displayClientMessage(
Lang.translateDirect(
train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"),
true);
player.getInventory()
.placeItemBackInInventory(train.runtime.returnSchedule());
// player.setItemInHand(event.getHand(), train.runtime.returnSchedule());
player.getInventory()
.placeItemBackInInventory(train.runtime.returnSchedule());
}
player.getCooldowns()
.addCooldown(AllItems.SCHEDULE.get(), 5);
event.setCancellationResult(InteractionResult.SUCCESS);
event.setCanceled(true);
return;
}

View file

@ -115,6 +115,8 @@ public abstract class EntityContraptionInteractionMixin extends CapabilityProvid
return;
if (self.isOnGround())
return;
if (self.isPassenger())
return;
Vec3 worldPos = self.position()
.add(0, -0.2, 0);