use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class EntityMixin method impl$onMoveCollide.
@Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;collide(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;"))
private Vec3 impl$onMoveCollide(final Entity entity, final Vec3 originalMove) {
final Vec3 afterCollide = this.shadow$collide(originalMove);
if (ShouldFire.COLLIDE_BLOCK_EVENT_MOVE && !originalMove.equals(afterCollide)) {
// We had a collision! Try to find the colliding block
// TODO this is not 100% accurate as the collision happens with the bb potentially colliding with multiple blocks
// TODO maybe actually check for blocks in bb?
BlockPos pos = new BlockPos(this.position.add(originalMove));
if (this.blockPosition.equals(pos)) {
// retry with bigger move for entities with big bounding box - e.g. minecart
pos = new BlockPos(this.position.add(originalMove.normalize()));
}
final BlockState state = this.level.getBlockState(pos);
final org.spongepowered.api.util.Direction dir = org.spongepowered.api.util.Direction.closest(new Vector3d(originalMove.x, originalMove.y, originalMove.z));
if (SpongeCommonEventFactory.handleCollideBlockEvent(state.getBlock(), this.level, pos, state, (Entity) (Object) this, dir, SpongeCommonEventFactory.CollisionType.MOVE)) {
return originalMove;
}
}
return afterCollide;
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class LivingEntityMixin method impl$onSetHeldItem.
@Redirect(method = "completeUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V"))
private void impl$onSetHeldItem(final LivingEntity self, final InteractionHand hand, final ItemStack stack) {
if (this.level.isClientSide) {
self.setItemInHand(hand, stack);
return;
}
// Unforunately, ItemFood calls ItemStack#shrink in Item#onItemUseFinish.
// To ensure that we provide the original ItemStack in the event,
// we make a copy of in our onUpdateItemUse redirect
// If the event or transaction is cancelled, we make sure to explicitly
// set the copy back in the player's hand, since it may have been already
// modified if an ItemFood is being used.
final ItemStackSnapshot activeItemStackSnapshot = ItemStackUtil.snapshotOf(this.impl$activeItemStackCopy == null ? ItemStack.EMPTY : this.impl$activeItemStackCopy);
final UseItemStackEvent.Replace event;
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack == null ? ItemStack.EMPTY : stack);
final HandType handType = (HandType) (Object) hand;
this.impl$addSelfToFrame(frame, activeItemStackSnapshot, handType);
final Ticks useItemRemainingTicks = Ticks.of(this.useItemRemaining);
event = SpongeEventFactory.createUseItemStackEventReplace(PhaseTracker.getCauseStackManager().currentCause(), useItemRemainingTicks, useItemRemainingTicks, activeItemStackSnapshot, new Transaction<>(ItemStackUtil.snapshotOf(this.impl$activeItemStackCopy), snapshot));
}
if (SpongeCommon.post(event)) {
this.shadow$setItemInHand(hand, this.impl$activeItemStackCopy.copy());
return;
}
if (!event.itemStackResult().isValid()) {
this.shadow$setItemInHand(hand, this.impl$activeItemStackCopy.copy());
return;
}
this.shadow$setItemInHand(hand, ItemStackUtil.fromSnapshotToNative(event.itemStackResult().finalReplacement()));
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class MobMixin method impl$getClosestPlayerForSpawning.
@Nullable
@Redirect(method = "checkDespawn()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getNearestPlayer(Lnet/minecraft/world/entity/Entity;D)Lnet/minecraft/world/entity/player/Player;"))
private Player impl$getClosestPlayerForSpawning(final Level world, final net.minecraft.world.entity.Entity entityIn, final double distance) {
double bestDistance = -1.0D;
Player result = null;
for (final Player player : world.players()) {
if (player == null || player.removed || !((PlayerBridge) player).bridge$affectsSpawning()) {
continue;
}
final double playerDistance = player.distanceToSqr(entityIn);
if ((distance < 0.0D || playerDistance < distance * distance) && (bestDistance == -1.0D || playerDistance < bestDistance)) {
bestDistance = playerDistance;
result = player;
}
}
return result;
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class PlayerListMixin method impl$callRespawnPlayerRecreateEvent.
@Redirect(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V", ordinal = 1))
private void impl$callRespawnPlayerRecreateEvent(final ServerGamePacketListenerImpl serverPlayNetHandler, final Packet<?> packetIn, final net.minecraft.server.level.ServerPlayer originalPlayer, final boolean keepAllPlayerData) {
final net.minecraft.server.level.ServerPlayer recreatedPlayer = serverPlayNetHandler.player;
final Vector3d originalPosition = VecHelper.toVector3d(originalPlayer.position());
final Vector3d destinationPosition = VecHelper.toVector3d(recreatedPlayer.position());
final org.spongepowered.api.world.server.ServerWorld originalWorld = (org.spongepowered.api.world.server.ServerWorld) originalPlayer.level;
final org.spongepowered.api.world.server.ServerWorld originalDestinationWorld = (org.spongepowered.api.world.server.ServerWorld) this.server.getLevel(this.impl$originalDestination == null ? Level.OVERWORLD : this.impl$originalDestination);
final org.spongepowered.api.world.server.ServerWorld destinationWorld = (org.spongepowered.api.world.server.ServerWorld) this.server.getLevel(this.impl$newDestination == null ? Level.OVERWORLD : this.impl$newDestination);
final RespawnPlayerEvent.Recreate event = SpongeEventFactory.createRespawnPlayerEventRecreate(PhaseTracker.getCauseStackManager().currentCause(), destinationPosition, originalWorld, originalPosition, destinationWorld, originalDestinationWorld, destinationPosition, (ServerPlayer) originalPlayer, (ServerPlayer) recreatedPlayer, this.impl$isGameMechanicRespawn, !keepAllPlayerData);
SpongeCommon.post(event);
recreatedPlayer.setPos(event.destinationPosition().x(), event.destinationPosition().y(), event.destinationPosition().z());
this.impl$isGameMechanicRespawn = false;
this.impl$originalDestination = null;
this.impl$newDestination = null;
final ServerLevel targetWorld = (ServerLevel) event.destinationWorld();
((ServerPlayerBridge) recreatedPlayer).bridge$sendChangeDimension(targetWorld.dimensionType(), ((ClientboundRespawnPacketAccessor) packetIn).accessor$dimension(), ((ClientboundRespawnPacketAccessor) packetIn).accessor$seed(), recreatedPlayer.gameMode.getGameModeForPlayer(), recreatedPlayer.gameMode.getPreviousGameModeForPlayer(), targetWorld.isDebug(), targetWorld.isFlat(), keepAllPlayerData);
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class ServerChunkCacheMixin method impl$useSerializationBehaviorWhenSaving.
// @formatter:on
@Redirect(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;saveAllChunks(Z)V"))
private void impl$useSerializationBehaviorWhenSaving(final ChunkMap chunkManager, final boolean flush) {
final ServerLevel world = this.level;
final SerializationBehavior serializationBehavior = ((ServerWorldProperties) world.getLevelData()).serializationBehavior();
if (serializationBehavior == SerializationBehavior.AUTOMATIC || serializationBehavior == SerializationBehavior.MANUAL) {
((ChunkMapAccessor) chunkManager).invoker$saveAllChunks(flush);
}
}
Aggregations