use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class ServerPlayerMixin_Tracker method tracker$throwItemDrop.
/**
* @author gabizou - June 4th, 2016
* @author i509VCB - February 17th, 2020 - 1.14.4
* @author gabizou - December 31st, 2021 - 1.16.5
* @reason We inject a construct event for the item drop and conveniently
* can redirect the super call.
*/
@Redirect(method = "drop", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;"))
@Nullable
private ItemEntity tracker$throwItemDrop(final Player thisPlayer, final ItemStack droppedItem, final boolean dropAround, final boolean traceItem) {
if (droppedItem.isEmpty()) {
return null;
}
if (((PlatformEntityBridge) this).bridge$isFakePlayer()) {
return super.shadow$drop(droppedItem, dropAround, traceItem);
}
if (((LevelBridge) this.level).bridge$isFake()) {
return super.shadow$drop(droppedItem, dropAround, traceItem);
}
final double posX1 = this.shadow$getX();
final double posY1 = this.shadow$getEyeY() - (double) 0.3F;
final double posZ1 = this.shadow$getZ();
// Now the real fun begins.
final ItemStack item;
final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(droppedItem);
final List<ItemStackSnapshot> original = new ArrayList<>();
original.add(snapshot);
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
item = SpongeCommonEventFactory.throwDropItemAndConstructEvent((ServerPlayer) (Object) this, posX1, posY1, posZ1, snapshot, original, frame);
if (item == null || item.isEmpty()) {
return null;
}
// Here is where we would potentially perform item pre-merging (merge the item stacks with previously captured item stacks
// and only if those stacks can be stacked (count increased). Otherwise, we'll just continue to throw the entity item.
// For now, due to refactoring a majority of all of this code, pre-merging is disabled entirely.
final ItemEntity itemEntity = new ItemEntity(this.level, posX1, posY1, posZ1, droppedItem);
itemEntity.setPickUpDelay(40);
if (traceItem) {
itemEntity.setThrower(this.shadow$getUUID());
}
final Random random = this.shadow$getRandom();
if (dropAround) {
final float f = random.nextFloat() * 0.5F;
final float f1 = random.nextFloat() * ((float) Math.PI * 2F);
itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f);
} else {
final float f8 = Mth.sin(this.xRot * ((float) Math.PI / 180F));
final float f2 = Mth.cos(this.xRot * ((float) Math.PI / 180F));
final float f3 = Mth.sin(this.yRot * ((float) Math.PI / 180F));
final float f4 = Mth.cos(this.yRot * ((float) Math.PI / 180F));
final float f5 = this.random.nextFloat() * ((float) Math.PI * 2F);
final float f6 = 0.02F * this.random.nextFloat();
itemEntity.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos(f5) * (double) f6, (-f8 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin(f5) * (double) f6);
}
return itemEntity;
}
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class PlayerListMixin_Tracker method tracker$trackPlayerLogoutThroughPhaseTracker.
@Redirect(method = "remove", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;removePlayerImmediately(Lnet/minecraft/server/level/ServerPlayer;)V"))
private void tracker$trackPlayerLogoutThroughPhaseTracker(final ServerLevel world, final ServerPlayer player) {
try (final GeneralizedContext context = PlayerPhase.State.PLAYER_LOGOUT.createPhaseContext(PhaseTracker.SERVER).source(player)) {
context.buildAndSwitch();
world.removePlayerImmediately(player);
}
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class LivingEntityMixin_Tracker method tracker$enterDeathPhase.
/**
* @author i509VCB
* @author gabizou
*
* @reason We can enter in to the entity drops transaction here which will
* successfully batch the side effects (this is effectively a singular side
* effect/transaction instead of a pipeline) to perform some things around
* the entity's death. This successfully records the transactions associated
* with this entity entering into the death state.
*/
@Redirect(method = "baseTick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;tickDeath()V"))
private void tracker$enterDeathPhase(final LivingEntity livingEntity) {
final PhaseTracker instance = PhaseTracker.SERVER;
if (!instance.onSidedThread()) {
this.shadow$tickDeath();
return;
}
if (((LevelBridge) this.level).bridge$isFake()) {
this.shadow$tickDeath();
return;
}
final PhaseContext<@NonNull ?> context = instance.getPhaseContext();
if (!context.doesBlockEventTracking()) {
this.shadow$tickDeath();
return;
}
try (final EffectTransactor ignored = context.getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) {
this.shadow$tickDeath();
}
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class CampfireBlockMixin method impl$spongeRedirectForFireDamage.
@Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private boolean impl$spongeRedirectForFireDamage(final Entity self, final DamageSource source, final float damage, final BlockState blockState, final Level world, final BlockPos blockPos, final Entity entity) {
if (self.level.isClientSide) {
// Short Circuit
return self.hurt(source, damage);
}
try {
final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ());
final DamageSource fire = MinecraftBlockDamageSource.ofFire("inFire", location, true);
((DamageSourceBridge) fire).bridge$setFireSource();
return self.hurt(DamageSource.IN_FIRE, damage);
} finally {
// Since "source" is already the DamageSource.IN_FIRE object, we can re-use it to re-assign.
((DamageSourceBridge) source).bridge$setFireSource();
}
}
use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.
the class FallingBlockMixin method impl$checkFallable.
@Redirect(method = "tick(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Ljava/util/Random;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;getY()I"))
public int impl$checkFallable(final BlockPos pos, final BlockState state, final ServerLevel world, final BlockPos samePos, final Random random, final CallbackInfo ci) {
if (pos.getY() < 0) {
return pos.getY();
}
if (!ShouldFire.CONSTRUCT_ENTITY_EVENT_PRE) {
return pos.getY();
}
final EntityType<org.spongepowered.api.entity.FallingBlock> fallingBlock = EntityTypes.FALLING_BLOCK.get();
final org.spongepowered.api.world.server.ServerWorld spongeWorld = (org.spongepowered.api.world.server.ServerWorld) world;
final BlockSnapshot snapshot = spongeWorld.createSnapshot(pos.getX(), pos.getY(), pos.getZ());
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(snapshot);
frame.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.FALLING_BLOCK);
final ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(frame.currentCause(), ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) world, pos.getX() + 0.5D, pos.getY(), pos.getZ() + 0.5D), new Vector3d(0, 0, 0), fallingBlock);
if (SpongeCommon.post(event)) {
return -1;
}
return pos.getY();
}
}
Aggregations