use of org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP in project SpongeCommon by SpongePowered.
the class DropItemWithHotkeyState method unwind.
@Override
public void unwind(InventoryPacketContext context) {
final EntityPlayerMP player = context.getPacketPlayer();
// final ItemStack usedStack = context.getItemUsed();
// final ItemStackSnapshot usedSnapshot = ItemStackUtil.snapshotOf(usedStack);
final Entity spongePlayer = EntityUtil.fromNative(player);
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(spongePlayer);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.DROPPED_ITEM);
context.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(blocks -> TrackingUtil.processBlockCaptures(blocks, this, context));
context.getCapturedItemsSupplier().acceptAndClearIfNotEmpty(items -> {
final ArrayList<Entity> entities = new ArrayList<>();
for (EntityItem item : items) {
entities.add(EntityUtil.fromNative(item));
}
int usedButton = 0;
if (context.getPacket() instanceof CPacketPlayerDigging) {
final CPacketPlayerDigging packetIn = context.getPacket();
usedButton = packetIn.getAction() == CPacketPlayerDigging.Action.DROP_ITEM ? PacketPhase.PACKET_BUTTON_PRIMARY_ID : 1;
} else {
final CPacketClickWindow packetIn = context.getPacket();
usedButton = packetIn.getUsedButton();
}
Transaction<ItemStackSnapshot> cursorTrans = new Transaction<>(ItemStackSnapshot.NONE, ItemStackSnapshot.NONE);
final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
List<SlotTransaction> slotTrans = mixinContainer.getCapturedTransactions();
ClickInventoryEvent.Drop dropItemEvent = ((DropItemWithHotkeyState) this).createInventoryEvent(player, ContainerUtil.fromNative(player.openContainer), cursorTrans, Lists.newArrayList(slotTrans), entities, usedButton);
SpongeImpl.postEvent(dropItemEvent);
if (dropItemEvent.isCancelled() || PacketPhaseUtil.allTransactionsInvalid(dropItemEvent.getTransactions())) {
((IMixinEntityPlayerMP) player).restorePacketItem(EnumHand.MAIN_HAND);
PacketPhaseUtil.handleSlotRestore(player, player.openContainer, dropItemEvent.getTransactions(), true);
} else {
processSpawnedEntities(player, dropItemEvent);
}
slotTrans.clear();
mixinContainer.setCaptureInventory(false);
});
context.getCapturedEntityDropSupplier().acceptIfNotEmpty(itemMapping -> {
});
final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
mixinContainer.setCaptureInventory(false);
mixinContainer.getCapturedTransactions().clear();
}
}
use of org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP in project SpongeCommon by SpongePowered.
the class MixinNetHandlerPlayServer method throwMoveEvent.
/**
* @author gabizou - June 22nd, 2016
* @reason Sponge has to throw the movement events before we consider moving the player and there's
* no clear way to go about it with the target position being null and the last position update checks.
* @param packetIn
*/
@Redirect(method = "processPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/EntityPlayerMP;queuedEndExit:Z"))
private boolean throwMoveEvent(EntityPlayerMP playerMP, CPacketPlayer packetIn) {
if (!playerMP.queuedEndExit) {
// We don't fire an event to avoid confusing plugins.
if (!packetIn.moving && !packetIn.rotating) {
return playerMP.queuedEndExit;
}
// Sponge Start - Movement event
Player player = (Player) this.player;
IMixinEntityPlayerMP mixinPlayer = (IMixinEntityPlayerMP) this.player;
Vector3d fromrot = player.getRotation();
// If Sponge used the player's current location, the delta might never be triggered which could be exploited
Location<World> from = player.getLocation();
if (this.lastMoveLocation != null) {
from = this.lastMoveLocation;
}
Vector3d torot = new Vector3d(packetIn.pitch, packetIn.yaw, 0);
Location<World> to = new Location<>(player.getWorld(), packetIn.x, packetIn.y, packetIn.z);
// Minecraft sends a 0, 0, 0 position when rotation only update occurs, this needs to be recognized and corrected
boolean rotationOnly = !packetIn.moving && packetIn.rotating;
if (rotationOnly) {
// Correct the to location so it's not misrepresented to plugins, only when player rotates without moving
// In this case it's only a rotation update, which isn't related to the to location
from = player.getLocation();
to = from;
}
// Minecraft does the same with rotation when it's only a positional update
boolean positionOnly = packetIn.moving && !packetIn.rotating;
if (positionOnly) {
// Correct the new rotation to match the old rotation
torot = fromrot;
}
((IMixinEntityPlayerMP) this.player).setVelocityOverride(to.getPosition().sub(from.getPosition()));
double deltaSquared = to.getPosition().distanceSquared(from.getPosition());
double deltaAngleSquared = fromrot.distanceSquared(torot);
// eventually it would be nice to not have them
if (deltaSquared > ((1f / 16) * (1f / 16)) || deltaAngleSquared > (.15f * .15f)) {
Transform<World> fromTransform = player.getTransform().setLocation(from).setRotation(fromrot);
Transform<World> toTransform = player.getTransform().setLocation(to).setRotation(torot);
Sponge.getCauseStackManager().pushCause(player);
MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), fromTransform, toTransform, player);
SpongeImpl.postEvent(event);
Sponge.getCauseStackManager().popCause();
if (event.isCancelled()) {
mixinPlayer.setLocationAndAngles(fromTransform);
this.lastMoveLocation = from;
((IMixinEntityPlayerMP) this.player).setVelocityOverride(null);
return true;
} else if (!event.getToTransform().equals(toTransform)) {
mixinPlayer.setLocationAndAngles(event.getToTransform());
this.lastMoveLocation = event.getToTransform().getLocation();
((IMixinEntityPlayerMP) this.player).setVelocityOverride(null);
return true;
} else if (!from.equals(player.getLocation()) && this.justTeleported) {
this.lastMoveLocation = player.getLocation();
// Prevent teleports during the move event from causing odd behaviors
this.justTeleported = false;
((IMixinEntityPlayerMP) this.player).setVelocityOverride(null);
return true;
} else {
this.lastMoveLocation = event.getToTransform().getLocation();
}
this.resendLatestResourcePackRequest();
}
}
return playerMP.queuedEndExit;
}
use of org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callDestructEntityEventDeath.
public static DestructEntityEvent.Death callDestructEntityEventDeath(EntityLivingBase entity, DamageSource source) {
final MessageEvent.MessageFormatter formatter = new MessageEvent.MessageFormatter();
MessageChannel originalChannel;
MessageChannel channel;
Text originalMessage;
Optional<User> sourceCreator = Optional.empty();
boolean messageCancelled = false;
if (entity instanceof EntityPlayerMP) {
originalChannel = channel = ((IMixinEntityPlayerMP) entity).getDeathMessageChannel();
} else {
originalChannel = MessageChannel.TO_NONE;
channel = MessageChannel.TO_NONE;
}
if (source instanceof EntityDamageSource) {
EntityDamageSource damageSource = (EntityDamageSource) source;
IMixinEntity spongeEntity = (IMixinEntity) damageSource.getImmediateSource();
if (spongeEntity != null) {
sourceCreator = spongeEntity.getCreatorUser();
}
}
originalMessage = SpongeTexts.toText(entity.getCombatTracker().getDeathMessage());
formatter.getBody().add(new MessageEvent.DefaultBodyApplier(originalMessage));
final boolean isMainThread = Sponge.isServerAvailable() && Sponge.getServer().isMainThread();
// checks need to be made here since entities can die on the client world.
try (final StackFrame frame = isMainThread ? Sponge.getCauseStackManager().pushCauseFrame() : null) {
if (isMainThread) {
Sponge.getCauseStackManager().pushCause(source);
if (sourceCreator.isPresent()) {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, sourceCreator.get());
}
}
final Cause cause = isMainThread ? Sponge.getCauseStackManager().getCurrentCause() : Cause.of(EventContext.empty(), source);
DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(cause, originalChannel, Optional.of(channel), formatter, (Living) entity, entity.world.getGameRules().getBoolean("keepInventory"), messageCancelled);
SpongeImpl.postEvent(event);
Text message = event.getMessage();
if (!event.isMessageCancelled() && !message.isEmpty()) {
event.getChannel().ifPresent(eventChannel -> eventChannel.send(entity, event.getMessage()));
}
return event;
}
}
use of org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP in project SpongeCommon by SpongePowered.
the class EntityUtil method transferPlayerToDimension.
// Used by PlayerList#transferPlayerToDimension and EntityPlayerMP#changeDimension.
// This method should NOT fire a teleport event as that should always be handled by the caller.
public static void transferPlayerToDimension(MoveEntityEvent.Teleport.Portal event, EntityPlayerMP playerIn) {
WorldServer fromWorld = (WorldServer) event.getFromTransform().getExtent();
WorldServer toWorld = (WorldServer) event.getToTransform().getExtent();
playerIn.dimension = WorldManager.getClientDimensionId(playerIn, toWorld);
toWorld.getChunkProvider().loadChunk(event.getToTransform().getLocation().getChunkPosition().getX(), event.getToTransform().getLocation().getChunkPosition().getZ());
// Support vanilla clients teleporting to custom dimensions
final int dimensionId = playerIn.dimension;
// Send dimension registration
if (((IMixinEntityPlayerMP) playerIn).usesCustomClient()) {
WorldManager.sendDimensionRegistration(playerIn, toWorld.provider);
} else {
// Force vanilla client to refresh its chunk cache if same dimension type
if (fromWorld != toWorld && fromWorld.provider.getDimensionType() == toWorld.provider.getDimensionType()) {
playerIn.connection.sendPacket(new SPacketRespawn((dimensionId >= 0 ? -1 : 0), toWorld.getDifficulty(), toWorld.getWorldInfo().getTerrainType(), playerIn.interactionManager.getGameType()));
}
}
playerIn.connection.sendPacket(new SPacketRespawn(dimensionId, toWorld.getDifficulty(), toWorld.getWorldInfo().getTerrainType(), playerIn.interactionManager.getGameType()));
fromWorld.removeEntityDangerously(playerIn);
playerIn.isDead = false;
// we do not need to call transferEntityToWorld as we already have the correct transform and created the portal in handleDisplaceEntityPortalEvent
((IMixinEntity) playerIn).setLocationAndAngles(event.getToTransform());
playerIn.setWorld(toWorld);
toWorld.spawnEntity(playerIn);
toWorld.updateEntityWithOptionalForce(playerIn, false);
SpongeImpl.getServer().getPlayerList().preparePlayer(playerIn, fromWorld);
playerIn.connection.setPlayerLocation(playerIn.posX, playerIn.posY, playerIn.posZ, playerIn.rotationYaw, playerIn.rotationPitch);
playerIn.interactionManager.setWorld(toWorld);
SpongeImpl.getServer().getPlayerList().updateTimeAndWeatherForPlayer(playerIn, toWorld);
SpongeImpl.getServer().getPlayerList().syncPlayerInventory(playerIn);
// Update reducedDebugInfo game rule
playerIn.connection.sendPacket(new SPacketEntityStatus(playerIn, toWorld.getGameRules().getBoolean(DefaultGameRules.REDUCED_DEBUG_INFO) ? (byte) 22 : 23));
for (PotionEffect potioneffect : playerIn.getActivePotionEffects()) {
playerIn.connection.sendPacket(new SPacketEntityEffect(playerIn.getEntityId(), potioneffect));
}
((IMixinEntityPlayerMP) playerIn).refreshXpHealthAndFood();
SpongeImplHooks.handlePostChangeDimensionEvent(playerIn, fromWorld, toWorld);
}
use of org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP in project SpongeCommon by SpongePowered.
the class HealthScalingProcessor method set.
@Override
protected boolean set(EntityPlayerMP dataHolder, Double value) {
if (value < 1D) {
return false;
}
if (value > Float.MAX_VALUE) {
return false;
}
final IMixinEntityPlayerMP mixinPlayer = (IMixinEntityPlayerMP) dataHolder;
if (value == 20D) {
mixinPlayer.setHealthScale(20);
mixinPlayer.setHealthScaled(true);
return true;
}
mixinPlayer.setHealthScale(value);
return true;
}
Aggregations