use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeForge by SpongePowered.
the class MixinBlockRailBase method onMinecartRailPass.
// Used to transfer tracking information from minecarts to block positions
@Inject(method = "onMinecartPass", at = @At(value = "HEAD"))
public void onMinecartRailPass(World world, net.minecraft.entity.item.EntityMinecart cart, BlockPos pos, CallbackInfo ci) {
IMixinEntity spongeEntity = (IMixinEntity) cart;
Optional<User> notifier = spongeEntity.getNotifierUser();
Optional<User> owner = spongeEntity.getCreatorUser();
if (owner.isPresent() || notifier.isPresent()) {
IMixinChunk spongeChunk = (IMixinChunk) world.getChunkFromBlockCoords(pos);
if (notifier.isPresent()) {
spongeChunk.addTrackedBlockPosition(world.getBlockState(pos).getBlock(), pos, notifier.get(), PlayerTracker.Type.NOTIFIER);
} else {
spongeChunk.addTrackedBlockPosition(world.getBlockState(pos).getBlock(), pos, owner.get(), PlayerTracker.Type.NOTIFIER);
}
}
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class PhaseTracker method spawnEntity.
/**
* This is the replacement of {@link WorldServer#spawnEntity(net.minecraft.entity.Entity)}
* where it captures into phases. The causes and relations are processed by the phases.
*
* The difference between {@link #spawnEntityWithCause(World, Entity)} is that it bypasses
* any phases and directly throws a spawn entity event.
*
* @param world The world
* @param entity The entity
* @return True if the entity spawn was successful
*/
public boolean spawnEntity(World world, Entity entity) {
checkNotNull(entity, "Entity cannot be null!");
// Sponge Start - handle construction phases
if (((IMixinEntity) entity).isInConstructPhase()) {
((IMixinEntity) entity).firePostConstructEvents();
}
final net.minecraft.entity.Entity minecraftEntity = EntityUtil.toNative(entity);
final WorldServer minecraftWorld = (WorldServer) world;
final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) minecraftWorld;
final PhaseData phaseData = this.stack.peek();
final IPhaseState<?> phaseState = phaseData.state;
final PhaseContext<?> context = phaseData.context;
final boolean isForced = minecraftEntity.forceSpawn || minecraftEntity instanceof EntityPlayer;
// Certain phases disallow entity spawns (such as block restoration)
if (!isForced && !phaseState.allowEntitySpawns()) {
return false;
}
// Sponge End - continue with vanilla mechanics
final int chunkX = MathHelper.floor(minecraftEntity.posX / 16.0D);
final int chunkZ = MathHelper.floor(minecraftEntity.posZ / 16.0D);
if (!isForced && !mixinWorldServer.isMinecraftChunkLoaded(chunkX, chunkZ, true)) {
return false;
}
if (minecraftEntity instanceof EntityPlayer) {
EntityPlayer entityplayer = (EntityPlayer) minecraftEntity;
minecraftWorld.playerEntities.add(entityplayer);
minecraftWorld.updateAllPlayersSleepingFlag();
SpongeImplHooks.firePlayerJoinSpawnEvent((EntityPlayerMP) entityplayer);
} else {
// Sponge start - check for vanilla owner
if (minecraftEntity instanceof IEntityOwnable) {
IEntityOwnable ownable = (IEntityOwnable) entity;
net.minecraft.entity.Entity owner = ownable.getOwner();
if (owner != null && owner instanceof EntityPlayer) {
context.owner = (User) owner;
entity.setCreator(ownable.getOwnerId());
}
} else if (minecraftEntity instanceof EntityThrowable) {
EntityThrowable throwable = (EntityThrowable) minecraftEntity;
EntityLivingBase thrower = throwable.getThrower();
if (thrower != null) {
User user = null;
if (!(thrower instanceof EntityPlayer)) {
user = ((IMixinEntity) thrower).getCreatorUser().orElse(null);
} else {
user = (User) thrower;
}
if (user != null) {
context.owner = user;
entity.setCreator(user.getUniqueId());
}
}
}
// Sponge end
}
// capture all entities until the phase is marked for completion.
if (!isForced) {
try {
return ((IPhaseState) phaseState).spawnEntityOrCapture(context, entity, chunkX, chunkZ);
} catch (Exception | NoClassDefFoundError e) {
// Just in case something really happened, we should print a nice exception for people to
// paste us
this.printExceptionSpawningEntity(context, e);
return false;
}
}
// Sponge end - continue on with the checks.
minecraftWorld.getChunkFromChunkCoords(chunkX, chunkZ).addEntity(minecraftEntity);
minecraftWorld.loadedEntityList.add(minecraftEntity);
// Sponge - Cannot add onEntityAdded to the access transformer because forge makes it public
mixinWorldServer.onSpongeEntityAdded(minecraftEntity);
return true;
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class PhaseTracker method spawnEntityWithCause.
/**
* The core implementation of {@link World#spawnEntity(Entity)} that
* bypasses any sort of cause tracking and throws an event directly
*
* @param world The world
* @param entity The entity
* @return True if entity was spawned, false if not
*/
public boolean spawnEntityWithCause(World world, Entity entity) {
checkNotNull(entity, "Entity cannot be null!");
// Sponge Start - handle construction phases
if (((IMixinEntity) entity).isInConstructPhase()) {
((IMixinEntity) entity).firePostConstructEvents();
}
final net.minecraft.entity.Entity minecraftEntity = EntityUtil.toNative(entity);
final WorldServer worldServer = (WorldServer) world;
final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) worldServer;
// Sponge End - continue with vanilla mechanics
final int chunkX = MathHelper.floor(minecraftEntity.posX / 16.0D);
final int chunkZ = MathHelper.floor(minecraftEntity.posZ / 16.0D);
final boolean isForced = minecraftEntity.forceSpawn || minecraftEntity instanceof EntityPlayer;
if (!isForced && !mixinWorldServer.isMinecraftChunkLoaded(chunkX, chunkZ, true)) {
return false;
}
// Sponge Start - throw an event
// We need to use an arraylist so that filtering will work.
final List<Entity> entities = new ArrayList<>(1);
entities.add(entity);
final SpawnEntityEvent.Custom event = SpongeEventFactory.createSpawnEntityEventCustom(Sponge.getCauseStackManager().getCurrentCause(), entities);
SpongeImpl.postEvent(event);
if (entity instanceof EntityPlayer || !event.isCancelled()) {
mixinWorldServer.forceSpawnEntity(entity);
}
return true;
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity 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.IMixinEntity in project SpongeCommon by SpongePowered.
the class EntityUtil method entityOnDropItem.
/**
* A simple redirected static util method for {@link Entity#entityDropItem(ItemStack, float)}
* for easy debugging.
* @param entity
* @param itemStack
* @param offsetY
* @return
*/
public static EntityItem entityOnDropItem(Entity entity, ItemStack itemStack, float offsetY) {
final IMixinEntity mixinEntity = EntityUtil.toMixin(entity);
final IMixinEntityPlayer mixinPlayer = entity instanceof Player ? (IMixinEntityPlayer) entity : null;
// Now the real fun begins.
final ItemStack item;
final double posX = entity.posX;
final double posY = entity.posY + offsetY;
final double posZ = entity.posZ;
if (itemStack.isEmpty()) {
return null;
}
// FIRST we want to throw the DropItemEvent.PRE
final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(itemStack);
final List<ItemStackSnapshot> original = new ArrayList<>();
original.add(snapshot);
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(entity);
final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of(snapshot), original);
SpongeImpl.postEvent(dropEvent);
if (dropEvent.isCancelled()) {
if (mixinPlayer != null) {
mixinPlayer.shouldRestoreInventory(true);
}
return null;
}
if (dropEvent.getDroppedItems().isEmpty()) {
return null;
}
// SECOND throw the ConstructEntityEvent
Transform<World> suggested = new Transform<>(mixinEntity.getWorld(), new Vector3d(posX, entity.posY + offsetY, posZ));
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.ITEM, suggested);
SpongeImpl.postEvent(event);
item = event.isCancelled() ? null : ItemStackUtil.fromSnapshotToNative(dropEvent.getDroppedItems().get(0));
if (item == null) {
if (mixinPlayer != null) {
mixinPlayer.shouldRestoreInventory(true);
}
return null;
}
final PhaseData peek = PhaseTracker.getInstance().getCurrentPhaseData();
final IPhaseState currentState = peek.state;
final PhaseContext<?> phaseContext = peek.context;
if (item.isEmpty()) {
return null;
}
if (!currentState.ignoresItemPreMerging() && SpongeImpl.getGlobalConfig().getConfig().getOptimizations().doDropsPreMergeItemDrops()) {
if (currentState.tracksEntitySpecificDrops()) {
final Multimap<UUID, ItemDropData> multimap = phaseContext.getCapturedEntityDropSupplier().get();
final Collection<ItemDropData> itemStacks = multimap.get(entity.getUniqueID());
SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).build());
return null;
}
final List<ItemDropData> itemStacks = phaseContext.getCapturedItemStackSupplier().get();
SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).build());
return null;
}
EntityItem entityitem = new EntityItem(entity.world, posX, posY, posZ, item);
entityitem.setDefaultPickupDelay();
// FIFTH - Capture the entity maybe?
if (currentState.doesCaptureEntityDrops()) {
if (currentState.tracksEntitySpecificDrops()) {
// We are capturing per entity drop
phaseContext.getCapturedEntityItemDropSupplier().get().put(entity.getUniqueID(), entityitem);
} else {
// We are adding to a general list - usually for EntityPhase.State.DEATH
phaseContext.getCapturedItemsSupplier().get().add(entityitem);
}
// Return the item, even if it wasn't spawned in the world.
return entityitem;
}
// FINALLY - Spawn the entity in the world if all else didn't fail
entity.world.spawnEntity(entityitem);
return entityitem;
}
}
Aggregations