use of net.minecraft.server.level.ServerPlayer in project SpongeCommon by SpongePowered.
the class CommandsMixin method impl$testPermissionAndPreventRecalculationWhenSendingNodes.
@Redirect(method = "fillUsableCommands", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;canUse(Ljava/lang/Object;)Z", remap = false))
private boolean impl$testPermissionAndPreventRecalculationWhenSendingNodes(final CommandNode<CommandSourceStack> commandNode, final Object source, final CommandNode<CommandSourceStack> rootCommandNode, final CommandNode<SharedSuggestionProvider> rootSuggestion, final CommandSourceStack sourceButTyped, final Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode) {
final ServerPlayer e = (ServerPlayer) sourceButTyped.getEntity();
final Map<CommandNode<CommandSourceStack>, List<CommandNode<SharedSuggestionProvider>>> playerNodes = this.impl$playerNodeCache.get(e);
final List<CommandNode<SharedSuggestionProvider>> existingNodes = playerNodes.get(commandNode);
if (existingNodes != null) {
if (!existingNodes.isEmpty()) {
boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion);
for (final CommandNode<SharedSuggestionProvider> node : existingNodes) {
// Because we don't control the client, we have to work around it here.
if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode) {
final ArgumentCommandNode<SharedSuggestionProvider, ?> argNode = (ArgumentCommandNode<SharedSuggestionProvider, ?>) node;
if (argNode.getCustomSuggestions() != null) {
// Rebuild the node without the custom suggestions.
rootSuggestion.addChild(this.impl$cloneArgumentCommandNodeWithoutSuggestions(argNode));
continue;
}
} else if (node instanceof ArgumentCommandNode && ((ArgumentCommandNode<?, ?>) node).getCustomSuggestions() != null) {
// no more custom suggestions
hasCustomSuggestionsAlready = true;
}
rootSuggestion.addChild(node);
}
}
// If empty, we have a node won't resolve (even if not complex), so we ignore it.
return false;
// If we have already processed this node and it appears in the suggestion node list, prevent a potentially costly
// canUse check as we know we can already use it.
} else if (!commandNodeToSuggestionNode.containsKey(commandNode) && !SpongeNodePermissionCache.canUse(rootCommandNode instanceof RootCommandNode, this.impl$commandManager.getDispatcher(), commandNode, sourceButTyped)) {
playerNodes.put(commandNode, Collections.emptyList());
return false;
}
if (commandNode instanceof SpongeArgumentCommandNode && ((SpongeArgumentCommandNode<?>) commandNode).isComplex()) {
final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion);
final CommandNode<SharedSuggestionProvider> finalCommandNode = ((SpongeArgumentCommandNode<?>) commandNode).getComplexSuggestions(rootSuggestion, commandNodeToSuggestionNode, playerNodes, !hasCustomSuggestionsAlready);
if (!this.impl$getChildrenFromNode(commandNode).isEmpty()) {
this.shadow$fillUsableCommands(commandNode, finalCommandNode, sourceButTyped, commandNodeToSuggestionNode);
}
return false;
}
// Normal node, handle it normally. We don't add to the playerNodeCache - the commandNodeToSuggestionNode map handles this.
return true;
}
use of net.minecraft.server.level.ServerPlayer in project SpongeCommon by SpongePowered.
the class PlayerMixin_Attack_Impl method attack.
// @formatter:on
/**
* @author gabizou - April 8th, 2016
* @author gabizou - April 11th, 2016 - Update for 1.9 - This enitre method was rewritten
* @author i509VCB - February 15th, 2020 - Update for 1.14.4
* @author gabizou - November 15th, 2020 - Update for 1.15.2
*
* @reason Rewrites the attack to throw an {@link AttackEntityEvent} prior
* to the ensuing {@link org.spongepowered.api.event.entity.DamageEntityEvent}. This should cover all cases where players are
* attacking entities and those entities override {@link LivingEntity#hurt(DamageSource, float)}
* and effectively bypass our damage event hooks.
*
* LVT Rename Table:
* float f | damage |
* float f1 | enchantmentDamage |
* float f2 | attackStrength |
* boolean flag | isStrongAttack |
* boolean flag1 | isSprintingAttack |
* boolean flag2 | isCriticalAttack | Whether critical particles will spawn and of course, multiply the output damage
* boolean flag3 | isSweapingAttack | Whether the player is sweaping an attack and will deal AoE damage
* int i | knockbackModifier | The knockback modifier, must be set from the event after it has been thrown
* float f4 | targetOriginalHealth | This is initially set as the entity original health
* boolean flag4 | litEntityOnFire | This is an internal flag to where if the attack failed, the entity is no longer set on fire
* int j | fireAspectModifier | Literally just to check that the weapon used has fire aspect enchantments
* double d0 | distanceWalkedDelta | This checks that the distance walked delta is more than the normal walking speed to evaluate if you're making a sweaping attack
* double d1 | targetMotionX | Current target entity motion x vector
* double d2 | targetMotionY | Current target entity motion y vector
* double d3 | targetMotionZ | Current target entity motion z vector
* boolean flag5 | attackSucceeded | Whether the attack event succeeded
*
* @param targetEntity The target entity
*/
@Overwrite
public void attack(final Entity targetEntity) {
// Sponge Start - Add SpongeImpl hook to override in forge as necessary
if (!PlatformHooks.INSTANCE.getEntityHooks().checkAttackEntity((net.minecraft.world.entity.player.Player) (Object) this, targetEntity)) {
return;
}
// Sponge End
if (targetEntity.isAttackable()) {
if (!targetEntity.skipAttackInteraction((net.minecraft.world.entity.player.Player) (Object) this)) {
// Sponge Start - Prepare our event values
// float damage = (float) this.getEntityAttribute(Attributes.ATTACK_DAMAGE).getAttributeValue();
final double originalBaseDamage = this.shadow$getAttribute(Attributes.ATTACK_DAMAGE).getValue();
float damage = (float) originalBaseDamage;
// Sponge End
float enchantmentDamage = 0.0F;
// Sponge Start - Redirect getting enchantments for our damage event handlers
// if (targetEntity instanceof LivingEntity) {
// enchantmentDamage = EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), ((LivingEntity) targetEntity).getCreatureAttribute());
// } else {
// enchantmentDamage = EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), CreatureAttribute.UNDEFINED);
// }
final float attackStrength = this.shadow$getAttackStrengthScale(0.5F);
final List<DamageFunction> originalFunctions = new ArrayList<>();
final MobType creatureAttribute = targetEntity instanceof LivingEntity ? ((LivingEntity) targetEntity).getMobType() : MobType.UNDEFINED;
final List<DamageFunction> enchantmentModifierFunctions = DamageEventUtil.createAttackEnchantmentFunction(this.shadow$getMainHandItem(), creatureAttribute, attackStrength);
// This is kept for the post-damage event handling
final List<DamageModifier> enchantmentModifiers = enchantmentModifierFunctions.stream().map(ModifierFunction::modifier).collect(Collectors.toList());
enchantmentDamage = (float) enchantmentModifierFunctions.stream().map(ModifierFunction::function).mapToDouble(function -> function.applyAsDouble(originalBaseDamage)).sum();
originalFunctions.addAll(enchantmentModifierFunctions);
// Sponge End
originalFunctions.add(DamageEventUtil.provideCooldownAttackStrengthFunction((net.minecraft.world.entity.player.Player) (Object) this, attackStrength));
damage = damage * (0.2F + attackStrength * attackStrength * 0.8F);
enchantmentDamage = enchantmentDamage * attackStrength;
this.shadow$resetAttackStrengthTicker();
if (damage > 0.0F || enchantmentDamage > 0.0F) {
final boolean isStrongAttack = attackStrength > 0.9F;
boolean isSprintingAttack = false;
boolean isCriticalAttack = false;
boolean isSweapingAttack = false;
int knockbackModifier = 0;
knockbackModifier = knockbackModifier + EnchantmentHelper.getKnockbackBonus((net.minecraft.world.entity.player.Player) (Object) this);
if (this.shadow$isSprinting() && isStrongAttack) {
// Sponge - Only play sound after the event has be thrown and not cancelled.
// this.world.playSound((EntityPlayer) null, this.posX, this.posY, this.posZ, SoundEvents.entity_player_attack_knockback, this.getSoundCategory(), 1.0F, 1.0F);
++knockbackModifier;
isSprintingAttack = true;
}
isCriticalAttack = isStrongAttack && this.fallDistance > 0.0F && !this.onGround && !this.shadow$onClimbable() && !this.shadow$isInWater() && !this.shadow$hasEffect(MobEffects.BLINDNESS) && !this.shadow$isPassenger() && targetEntity instanceof LivingEntity;
isCriticalAttack = isCriticalAttack && !this.shadow$isSprinting();
final EventHooks.CriticalHitResult criticalResult = PlatformHooks.INSTANCE.getEventHooks().callCriticalHitEvent((net.minecraft.world.entity.player.Player) (Object) this, targetEntity, isCriticalAttack, isCriticalAttack ? 1.5F : 1.0F);
isCriticalAttack = criticalResult.criticalHit;
if (isCriticalAttack) {
// Sponge Start - add critical attack tuple
// damage *= 1.5F; // Sponge - This is handled in the event
originalFunctions.add(DamageEventUtil.provideCriticalAttackTuple((net.minecraft.world.entity.player.Player) (Object) this, criticalResult.modifier));
// Sponge End
}
// damage = damage + enchantmentDamage; // Sponge - We don't need this since our event will re-assign the damage to deal
final double distanceWalkedDelta = (double) (this.walkDist - this.walkDistO);
final ItemStack heldItem = this.shadow$getMainHandItem();
if (isStrongAttack && !isCriticalAttack && !isSprintingAttack && this.onGround && distanceWalkedDelta < (double) this.shadow$getSpeed()) {
if (heldItem.getItem() instanceof SwordItem) {
isSweapingAttack = true;
}
}
// Sponge Start - Create the event and throw it
final DamageSource damageSource = DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this);
final boolean isMainthread = !this.level.isClientSide;
if (isMainthread) {
PhaseTracker.getInstance().pushCause(damageSource);
}
final Cause currentCause = isMainthread ? PhaseTracker.getInstance().currentCause() : Cause.of(EventContext.empty(), damageSource);
final AttackEntityEvent event = SpongeEventFactory.createAttackEntityEvent(currentCause, (org.spongepowered.api.entity.Entity) targetEntity, originalFunctions, knockbackModifier, originalBaseDamage);
SpongeCommon.post(event);
if (isMainthread) {
PhaseTracker.getInstance().popCause();
}
if (event.isCancelled()) {
return;
}
damage = (float) event.finalOutputDamage();
// Sponge End
// Sponge Start - need final for later events
final double attackDamage = damage;
knockbackModifier = (int) event.knockbackModifier();
enchantmentDamage = (float) enchantmentModifiers.stream().mapToDouble(event::outputDamage).sum();
// Sponge End
float targetOriginalHealth = 0.0F;
boolean litEntityOnFire = false;
final int fireAspectModifier = EnchantmentHelper.getFireAspect((net.minecraft.world.entity.player.Player) (Object) this);
if (targetEntity instanceof LivingEntity) {
targetOriginalHealth = ((LivingEntity) targetEntity).getHealth();
if (fireAspectModifier > 0 && !targetEntity.isOnFire()) {
litEntityOnFire = true;
targetEntity.setSecondsOnFire(1);
}
}
final net.minecraft.world.phys.Vec3 targetMotion = targetEntity.getDeltaMovement();
final boolean attackSucceeded = targetEntity.hurt(DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this), damage);
if (attackSucceeded) {
if (knockbackModifier > 0) {
if (targetEntity instanceof LivingEntity) {
((LivingEntity) targetEntity).knockback((float) knockbackModifier * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)));
} else {
targetEntity.push((double) (-Mth.sin(this.yRot * 0.017453292F) * (float) knockbackModifier * 0.5F), 0.1D, (double) (Mth.cos(this.yRot * 0.017453292F) * (float) knockbackModifier * 0.5F));
}
this.shadow$setDeltaMovement(this.shadow$getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
this.shadow$setSprinting(false);
}
if (isSweapingAttack) {
for (final LivingEntity livingEntity : this.level.getEntitiesOfClass(LivingEntity.class, targetEntity.getBoundingBox().inflate(1.0D, 0.25D, 1.0D))) {
if (livingEntity != (net.minecraft.world.entity.player.Player) (Object) this && livingEntity != targetEntity && !this.shadow$isAlliedTo(livingEntity) && (!(livingEntity instanceof ArmorStand) || !((ArmorStand) livingEntity).isMarker()) && this.shadow$distanceToSqr(livingEntity) < 9.0D) {
// Sponge Start - Do a small event for these entities
// livingEntity.knockBack(this, 0.4F, (double)MathHelper.sin(this.rotationYaw * 0.017453292F), (double)(-MathHelper.cos(this.rotationYaw * 0.017453292F)));
// livingEntity.attackEntityFrom(DamageSource.causePlayerDamage(this), 1.0F);
final EntityDamageSource sweepingAttackSource = EntityDamageSource.builder().entity((org.spongepowered.api.entity.living.player.Player) this).type(DamageTypes.SWEEPING_ATTACK).build();
try (final CauseStackManager.StackFrame frame = isMainthread ? PhaseTracker.getInstance().pushCauseFrame() : null) {
if (isMainthread) {
frame.pushCause(sweepingAttackSource);
}
final ItemStackSnapshot heldSnapshot = ItemStackUtil.snapshotOf(heldItem);
if (isMainthread) {
frame.addContext(EventContextKeys.WEAPON, heldSnapshot);
}
final DamageFunction sweapingFunction = DamageFunction.of(DamageModifier.builder().cause(Cause.of(EventContext.empty(), heldSnapshot)).item(heldSnapshot).type(DamageModifierTypes.SWEEPING).build(), incoming -> EnchantmentHelper.getSweepingDamageRatio((net.minecraft.world.entity.player.Player) (Object) this) * attackDamage);
final List<DamageFunction> sweapingFunctions = new ArrayList<>();
sweapingFunctions.add(sweapingFunction);
final AttackEntityEvent sweepingAttackEvent = SpongeEventFactory.createAttackEntityEvent(currentCause, (org.spongepowered.api.entity.Entity) livingEntity, sweapingFunctions, 1, 1.0D);
SpongeCommon.post(sweepingAttackEvent);
if (!sweepingAttackEvent.isCancelled()) {
livingEntity.knockback(sweepingAttackEvent.knockbackModifier() * 0.4F, (double) Mth.sin(this.yRot * ((float) Math.PI / 180F)), (double) -Mth.cos(this.yRot * ((float) Math.PI / 180F)));
livingEntity.hurt(DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this), (float) sweepingAttackEvent.finalOutputDamage());
}
}
// Sponge End
}
}
if (this.bridge$vanishState().createsSounds()) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
this.shadow$sweepAttack();
}
if (targetEntity instanceof ServerPlayer && targetEntity.hurtMarked) {
((ServerPlayer) targetEntity).connection.send(new ClientboundSetEntityMotionPacket(targetEntity));
targetEntity.hurtMarked = false;
targetEntity.setDeltaMovement(targetMotion);
}
if (isCriticalAttack) {
if (this.bridge$vanishState().createsSounds()) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
this.shadow$crit(targetEntity);
}
if (!isCriticalAttack && !isSweapingAttack && this.bridge$vanishState().createsSounds()) {
if (isStrongAttack) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.shadow$getSoundSource(), 1.0F, 1.0F);
} else {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
}
if (enchantmentDamage > 0.0F) {
this.shadow$magicCrit(targetEntity);
}
this.shadow$setLastHurtMob(targetEntity);
if (targetEntity instanceof LivingEntity) {
EnchantmentHelper.doPostHurtEffects((LivingEntity) targetEntity, (net.minecraft.world.entity.player.Player) (Object) this);
}
EnchantmentHelper.doPostDamageEffects((net.minecraft.world.entity.player.Player) (Object) this, targetEntity);
final ItemStack itemstack1 = this.shadow$getMainHandItem();
Entity entity = targetEntity;
// Sponge - Forge compatibility for multi-part entities
entity = PlatformHooks.INSTANCE.getEntityHooks().getParentPart(entity);
if (!this.level.isClientSide && !itemstack1.isEmpty() && entity instanceof LivingEntity) {
itemstack1.hurtEnemy((LivingEntity) entity, (net.minecraft.world.entity.player.Player) (Object) this);
if (itemstack1.isEmpty()) {
// Sponge - platform hook for forge
PlatformHooks.INSTANCE.getEventHooks().callItemDestroyedEvent((net.minecraft.world.entity.player.Player) (Object) this, itemstack1, InteractionHand.MAIN_HAND);
this.shadow$setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY);
}
// Sponge Start
final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext();
final TransactionalCaptureSupplier transactor = context.getTransactor();
transactor.logPlayerInventoryChange((net.minecraft.world.entity.player.Player) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD);
// capture
this.inventoryMenu.broadcastChanges();
// Spong End
}
if (targetEntity instanceof LivingEntity) {
final float f5 = targetOriginalHealth - ((LivingEntity) targetEntity).getHealth();
this.shadow$awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F));
if (fireAspectModifier > 0) {
targetEntity.setSecondsOnFire(fireAspectModifier * 4);
}
if (this.level instanceof ServerWorld && f5 > 2.0F) {
final int k = (int) ((double) f5 * 0.5D);
((net.minecraft.server.level.ServerLevel) this.level).sendParticles(ParticleTypes.DAMAGE_INDICATOR, targetEntity.getX(), targetEntity.getY() + (double) (targetEntity.getBbHeight() * 0.5F), targetEntity.getZ(), k, 0.1D, 0.0D, 0.1D, 0.2D);
}
}
this.shadow$causeFoodExhaustion(0.1F);
} else {
if (this.bridge$vanishState().createsSounds()) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
if (litEntityOnFire) {
targetEntity.clearFire();
}
}
}
}
}
}
use of net.minecraft.server.level.ServerPlayer in project SpongeCommon by SpongePowered.
the class FishingHookMixin method retrieve.
/**
* @author Aaron1011 - February 6th, 2015
* @author Minecrell - December 24th, 2016 (Updated to Minecraft 1.11.2)
* @author Minecrell - June 14th, 2017 (Rewritten to handle cases where no items are dropped)
* @reason This needs to handle for both cases where a fish and/or an entity is being caught.
*/
@Overwrite
public int retrieve(final ItemStack stack) {
final Player playerEntity = this.shadow$getPlayerOwner();
if (!this.level.isClientSide && playerEntity != null) {
int i = 0;
// Sponge start
final List<Transaction<@NonNull ItemStackSnapshot>> transactions;
if (this.nibble > 0) {
// Moved from below
final LootContext.Builder lootcontext$builder = new LootContext.Builder((ServerLevel) this.level).withParameter(LootContextParams.ORIGIN, this.shadow$position()).withParameter(LootContextParams.TOOL, stack).withParameter(LootContextParams.THIS_ENTITY, (FishingHook) (Object) this).withRandom(this.random).withLuck((float) this.luck + playerEntity.getLuck());
final LootTable lootTable = this.level.getServer().getLootTables().get(BuiltInLootTables.FISHING);
final List<ItemStack> list = lootTable.getRandomItems(lootcontext$builder.create(LootContextParamSets.FISHING));
transactions = list.stream().map(ItemStackUtil::snapshotOf).map(snapshot -> new Transaction<>(snapshot, snapshot)).collect(Collectors.toList());
CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) playerEntity, stack, (FishingHook) (Object) this, list);
} else {
transactions = new ArrayList<>();
}
PhaseTracker.getCauseStackManager().pushCause(playerEntity);
if (SpongeCommon.post(SpongeEventFactory.createFishingEventStop(PhaseTracker.getCauseStackManager().currentCause(), ((FishingBobber) this), transactions))) {
// Event is cancelled
return 0;
}
if (this.hookedIn != null) {
this.bringInHookedEntity();
CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) playerEntity, stack, (FishingHook) (Object) this, Collections.emptyList());
this.level.broadcastEntityEvent((FishingHook) (Object) this, (byte) 31);
i = this.hookedIn instanceof ItemEntity ? 3 : 5;
}
// Sponge start - Moved up to event call
if (!transactions.isEmpty()) {
// Use transactions
for (final Transaction<@NonNull ItemStackSnapshot> transaction : transactions) {
if (!transaction.isValid()) {
continue;
}
final ItemStack itemstack = (ItemStack) (Object) transaction.finalReplacement().createStack();
// Sponge end
final ItemEntity entityitem = new ItemEntity(this.level, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), itemstack);
final double d0 = playerEntity.getX() - this.shadow$getX();
final double d1 = playerEntity.getY() - this.shadow$getY();
final double d2 = playerEntity.getZ() - this.shadow$getZ();
final double d3 = Mth.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
// double d4 = 0.1D;
entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Mth.sqrt(d3) * 0.08D, d2 * 0.1D);
this.level.addFreshEntity(entityitem);
playerEntity.level.addFreshEntity(new ExperienceOrb(playerEntity.level, playerEntity.getX(), playerEntity.getY() + 0.5D, playerEntity.getZ() + 0.5D, this.random.nextInt(6) + 1));
final Item item = itemstack.getItem();
if (item.is(ItemTags.FISHES)) {
playerEntity.awardStat(Stats.FISH_CAUGHT, 1);
}
}
PhaseTracker.getCauseStackManager().popCause();
// Sponge: Don't lower damage if we've also caught an entity
i = Math.max(i, 1);
}
if (this.onGround) {
i = 2;
}
this.shadow$remove();
return i;
} else {
return 0;
}
}
use of net.minecraft.server.level.ServerPlayer in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method tracker$triggerInternalExplosion.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Explosion tracker$triggerInternalExplosion(org.spongepowered.api.world.explosion.Explosion explosion, final Function<? super Explosion, ? extends PhaseContext<@NonNull ?>> contextCreator) {
// Sponge start
final Explosion originalExplosion = (Explosion) explosion;
if (ShouldFire.EXPLOSION_EVENT_PRE) {
// Set up the pre event
final ExplosionEvent.Pre event = SpongeEventFactory.createExplosionEventPre(PhaseTracker.SERVER.currentCause(), explosion, ((org.spongepowered.api.world.server.ServerWorld) this));
if (SpongeCommon.post(event)) {
return (Explosion) explosion;
}
explosion = event.explosion();
}
final Explosion mcExplosion;
try {
// Since we already have the API created implementation Explosion, let's use it.
mcExplosion = (Explosion) explosion;
} catch (final Exception e) {
new org.spongepowered.asm.util.PrettyPrinter(60).add("Explosion not compatible with this implementation").centre().hr().add("An explosion that was expected to be used for this implementation does not").add("originate from this implementation.").add(e).trace();
return originalExplosion;
}
try (final PhaseContext<@NonNull ?> ignored = contextCreator.apply(mcExplosion).source(((Optional) explosion.sourceExplosive()).orElse(this))) {
ignored.buildAndSwitch();
final boolean damagesTerrain = explosion.shouldBreakBlocks();
// Sponge End
mcExplosion.explode();
mcExplosion.finalizeExplosion(true);
if (!damagesTerrain) {
mcExplosion.clearToBlow();
}
// the players being moved.
for (final ServerPlayer playerEntity : this.players) {
final Vec3 knockback = mcExplosion.getHitPlayers().get(playerEntity);
if (knockback != null) {
// In Vanilla, doExplosionB always updates the 'motion[xyz]' fields for every entity in range.
// However, this field is completely ignored for players (since 'velocityChanged') is never set, and
// a completely different value is sent through 'SPacketExplosion'.
// To replicate this behavior, we manually send a velocity packet. It's critical that we don't simply
// add to the 'motion[xyz]' fields, as that will end up using the value set by 'doExplosionB', which must be
// ignored.
playerEntity.connection.send(new ClientboundSetEntityMotionPacket(playerEntity.getId(), new Vec3(knockback.x, knockback.y, knockback.z)));
}
}
// Sponge End
}
// Sponge End
return mcExplosion;
}
use of net.minecraft.server.level.ServerPlayer in project SpongeCommon by SpongePowered.
the class ServerPlayerMixin_Inventory method inventory$switchToCloseWindowState.
@Override
protected void inventory$switchToCloseWindowState(final AbstractContainerMenu container, final Player player) {
// Corner case where the server is shutting down on the client, the server player is also being killed off.
if (Sponge.isServerAvailable() && Sponge.isClientAvailable()) {
container.removed(player);
return;
}
final ServerPlayer serverPlayer = (ServerPlayer) player;
try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.SERVER).source(serverPlayer).packetPlayer(serverPlayer)) {
ctx.buildAndSwitch();
try (final EffectTransactor ignored = ctx.getTransactor().logCloseInventory(player, true)) {
// Drop & capture cursor item
container.removed(player);
container.broadcastChanges();
}
}
// Handle Viewers
this.impl$onCloseMenu();
}
Aggregations