use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.
the class DamageSourceMixin method onSetExplosionSource.
@Inject(method = "explosion(Lnet/minecraft/world/level/Explosion;)Lnet/minecraft/world/damagesource/DamageSource;", at = @At("HEAD"), cancellable = true)
private static void onSetExplosionSource(@Nullable final Explosion explosion, final CallbackInfoReturnable<net.minecraft.world.damagesource.DamageSource> cir) {
if (explosion != null) {
final Entity entity = ((ExplosionAccessor) explosion).accessor$source();
if (entity != null && !((LevelBridge) ((ExplosionAccessor) explosion).accessor$level()).bridge$isFake()) {
if (explosion.getSourceMob() == null && entity instanceof CreatorTrackedBridge) {
// check creator
final CreatorTrackedBridge creatorBridge = (CreatorTrackedBridge) entity;
creatorBridge.tracker$getCreatorUUID().flatMap(x -> Sponge.server().player(x)).ifPresent(player -> {
final IndirectEntityDamageSource damageSource = new IndirectEntityDamageSource("explosion.player", entity, (Entity) player);
damageSource.setScalesWithDifficulty().setExplosion();
cir.setReturnValue(damageSource);
});
}
}
}
}
use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.
the class IndirectEntityDamageSourceMixin method onConstruct.
@Inject(method = "<init>", at = @At("RETURN"))
private void onConstruct(final CallbackInfo callbackInfo) {
if (this.entity != null) {
// sources can be null
final Entity mcEntity = this.shadow$getEntity();
this.impl$creatorUUID = mcEntity instanceof CreatorTrackedBridge ? ((CreatorTrackedBridge) mcEntity).tracker$getCreatorUUID().orElse(null) : null;
if (this.owner == null && this.impl$creatorUUID != null) {
final ServerPlayer player = SpongeCommon.server().getPlayerList().getPlayer(this.impl$creatorUUID);
if (player != null) {
this.owner = player;
}
}
}
}
use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.
the class TrackingUtil method tickTileEntity.
@SuppressWarnings({ "unused", "try" })
public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, final TickableBlockEntity tile) {
checkArgument(tile instanceof BlockEntity, "ITickable %s is not a TileEntity!", tile);
checkNotNull(tile, "Cannot capture on a null ticking tile entity!");
final net.minecraft.world.level.block.entity.BlockEntity tileEntity = (net.minecraft.world.level.block.entity.BlockEntity) tile;
final BlockEntityBridge mixinTileEntity = (BlockEntityBridge) tile;
final BlockPos pos = tileEntity.getBlockPos();
final LevelChunkBridge chunk = ((ActiveChunkReferantBridge) tile).bridge$getActiveChunk();
if (!((TrackableBridge) tileEntity).bridge$shouldTick()) {
return;
}
if (chunk == null) {
((ActiveChunkReferantBridge) tile).bridge$setActiveChunk((TrackedLevelChunkBridge) tileEntity.getLevel().getChunkAt(tileEntity.getBlockPos()));
}
final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(PhaseTracker.SERVER).source(mixinTileEntity);
try (final PhaseContext<?> phaseContext = context) {
if (tile instanceof CreatorTrackedBridge) {
// Add notifier and owner so we don't have to perform lookups during the phases and other processing
((CreatorTrackedBridge) tile).tracker$getNotifierUUID().ifPresent(phaseContext::notifier);
// Allow the tile entity to validate the owner of itself. As long as the tile entity
// chunk is already loaded and activated, and the tile entity has already loaded
// the owner of itself.
((CreatorTrackedBridge) tile).tracker$getCreatorUUID().ifPresent(phaseContext::creator);
}
// Finally, switch the context now that we have the owner and notifier
phaseContext.buildAndSwitch();
try (final Timing timing = ((TimingBridge) tileEntity.getType()).bridge$timings().startTiming()) {
tile.tick();
}
// otherwise the viewing players update this during their ticking
if (tileEntity instanceof ViewableInventoryBridge) {
final Set<ServerPlayer> players = ((ViewableInventoryBridge) tileEntity).viewableBridge$getViewers();
if (players.size() > 0) {
players.forEach(player -> player.containerMenu.broadcastChanges());
}
}
} catch (final Exception e) {
PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, context);
}
// We delay clearing active chunk if TE is invalidated during tick so we must remove it after
if (tileEntity.isRemoved()) {
((ActiveChunkReferantBridge) tileEntity).bridge$setActiveChunk(null);
}
}
use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callDestructEntityEventDeath.
public static DestructEntityEvent.Death callDestructEntityEventDeath(final LivingEntity entity, @Nullable final DamageSource source, final Audience originalChannel) {
final Component originalMessage;
Optional<UUID> sourceCreator = Optional.empty();
final boolean messageCancelled = false;
if (source instanceof EntityDamageSource) {
final EntityDamageSource damageSource = (EntityDamageSource) source;
if (damageSource.getDirectEntity() instanceof CreatorTrackedBridge) {
final CreatorTrackedBridge creatorBridge = (CreatorTrackedBridge) damageSource.getDirectEntity();
if (creatorBridge != null) {
sourceCreator = creatorBridge.tracker$getCreatorUUID();
}
}
}
originalMessage = SpongeAdventure.asAdventure(entity.getCombatTracker().getDeathMessage());
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
if (source != null) {
frame.pushCause(source);
}
sourceCreator.ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
final DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(frame.currentCause(), originalChannel, Optional.of(originalChannel), originalMessage, originalMessage, (Living) entity, entity.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY), messageCancelled);
SpongeCommon.post(event);
return event;
}
}
use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method handleCollideBlockEvent.
public static boolean handleCollideBlockEvent(final Block block, final Level world, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState state, final net.minecraft.world.entity.Entity entity, final Direction direction, final CollisionType type) {
if (world.isClientSide() || pos.getY() <= 0) {
return false;
}
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(entity);
if (entity instanceof CreatorTrackedBridge) {
final CreatorTrackedBridge spongeEntity = (CreatorTrackedBridge) entity;
spongeEntity.tracker$getCreatorUUID().ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
}
// TODO: Add target side support
final ServerLocation loc = ServerLocation.of((ServerWorld) world, VecHelper.toVector3d(pos));
final CollideBlockEvent event;
switch(type) {
case MOVE:
event = SpongeEventFactory.createCollideBlockEventMove(frame.currentCause(), (BlockState) state, loc, direction);
break;
case FALL:
event = SpongeEventFactory.createCollideBlockEventFall(frame.currentCause(), (BlockState) state, loc, direction);
break;
case STEP_ON:
event = SpongeEventFactory.createCollideBlockEventStepOn(frame.currentCause(), (BlockState) state, loc, direction);
break;
case INSIDE:
event = SpongeEventFactory.createCollideBlockEventInside(frame.currentCause(), (BlockState) state, loc, direction);
break;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
final boolean cancelled = SpongeCommon.post(event);
if (!cancelled) {
final EntityBridge spongeEntity = (EntityBridge) entity;
if (!pos.equals(spongeEntity.bridge$getLastCollidedBlockPos())) {
final PhaseContext<?> context = PhaseTracker.getInstance().getPhaseContext();
context.applyNotifierIfAvailable(notifier -> {
LevelChunkBridge spongeChunk = ((ActiveChunkReferantBridge) entity).bridge$getActiveChunk();
if (spongeChunk == null) {
spongeChunk = (LevelChunkBridge) world.getChunkAt(pos);
}
spongeChunk.bridge$addTrackedBlockPosition(block, pos, notifier, PlayerTracker.Type.NOTIFIER);
});
}
}
return cancelled;
}
}
Aggregations