use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeForge by SpongePowered.
the class SpongeForgeEventFactory method createChangeBlockEventBreak.
public static ChangeBlockEvent.Break createChangeBlockEventBreak(BlockEvent.BreakEvent forgeEvent) {
final BlockPos pos = forgeEvent.getPos();
final net.minecraft.world.World world = forgeEvent.getWorld();
if (world.isRemote) {
return null;
}
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData data = phaseTracker.getCurrentPhaseData();
BlockSnapshot originalSnapshot = ((World) forgeEvent.getWorld()).createSnapshot(pos.getX(), pos.getY(), pos.getZ());
BlockSnapshot finalSnapshot = BlockTypes.AIR.getDefaultState().snapshotFor(new Location<>((World) world, VecHelper.toVector3d(pos)));
ImmutableList<Transaction<BlockSnapshot>> blockSnapshots = new ImmutableList.Builder<Transaction<BlockSnapshot>>().add(new Transaction<>(originalSnapshot, finalSnapshot)).build();
User owner = data.context.getOwner().orElse(null);
User notifier = data.context.getNotifier().orElse(null);
EntityPlayer player = forgeEvent.getPlayer();
if (SpongeImplHooks.isFakePlayer(player)) {
Sponge.getCauseStackManager().addContext(EventContextKeys.FAKE_PLAYER, EntityUtil.toPlayer(player));
} else if (Sponge.getCauseStackManager().getCurrentCause() == null) {
Sponge.getCauseStackManager().pushCause(player);
}
if (owner != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
if (Sponge.getCauseStackManager().getCurrentCause() == null) {
Sponge.getCauseStackManager().pushCause(owner);
}
} else {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, (User) player);
if (Sponge.getCauseStackManager().getCurrentCause() == null) {
Sponge.getCauseStackManager().pushCause(player);
}
}
if (notifier != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
}
Sponge.getCauseStackManager().addContext(EventContextKeys.PLAYER_BREAK, (World) world);
return SpongeEventFactory.createChangeBlockEventBreak(Sponge.getCauseStackManager().getCurrentCause(), blockSnapshots);
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeForge by SpongePowered.
the class MixinBlockLeaves method onBreakBlock.
@Redirect(method = "breakBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;beginLeavesDecay(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)V", remap = false))
public void onBreakBlock(Block block, IBlockState state, net.minecraft.world.World worldIn, BlockPos pos) {
if (!worldIn.isRemote) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final IPhaseState currentState = phaseTracker.getCurrentState();
final boolean isBlockAlready = currentState.getPhase() != TrackingPhases.BLOCK;
@Nullable PhaseContext<?> blockDecay = null;
final boolean isWorldGen = currentState.isWorldGeneration();
if (isBlockAlready && !isWorldGen) {
final LocatableBlock locatable = LocatableBlock.builder().location(new Location<World>((World) worldIn, pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build();
blockDecay = BlockPhase.State.BLOCK_DECAY.createPhaseContext().source(locatable);
}
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame();
PhaseContext<?> context = blockDecay != null ? blockDecay.buildAndSwitch() : null) {
frame.addContext(EventContextKeys.LEAVES_DECAY, (World) worldIn);
if (SpongeCommonEventFactory.callChangeBlockEventPre((IMixinWorldServer) worldIn, pos).isCancelled()) {
return;
}
block.beginLeavesDecay(state, worldIn, pos);
}
} else {
block.beginLeavesDecay(state, worldIn, pos);
}
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeForge by SpongePowered.
the class MixinBlockLog method onBreakBlock.
@Redirect(method = "breakBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;beginLeavesDecay(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)V", remap = false))
public void onBreakBlock(Block block, IBlockState state, net.minecraft.world.World worldIn, BlockPos pos) {
if (!worldIn.isRemote) {
if (SpongeCommonEventFactory.callChangeBlockEventPre((IMixinWorldServer) worldIn, pos).isCancelled()) {
return;
}
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final IPhaseState currentState = phaseTracker.getCurrentState();
final boolean isBlockAlready = currentState.getPhase() != TrackingPhases.BLOCK;
final boolean isWorldGen = currentState.isWorldGeneration();
if (isBlockAlready && !isWorldGen) {
final LocatableBlock locatable = LocatableBlock.builder().location(new Location<World>((World) worldIn, pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build();
BlockPhase.State.BLOCK_DECAY.createPhaseContext().source(locatable).buildAndSwitch();
}
block.beginLeavesDecay(state, worldIn, pos);
if (isBlockAlready && !isWorldGen) {
phaseTracker.completePhase(BlockPhase.State.BLOCK_DECAY);
}
} else {
block.beginLeavesDecay(state, worldIn, pos);
}
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeForge by SpongePowered.
the class SpongeChunkGeneratorForge method populate.
@Override
public void populate(int chunkX, int chunkZ) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
this.chunkGeneratorTiming.startTimingIfSync();
this.rand.setSeed(this.world.getSeed());
long i1 = this.rand.nextLong() / 2L * 2L + 1L;
long j1 = this.rand.nextLong() / 2L * 2L + 1L;
this.rand.setSeed(chunkX * i1 + chunkZ * j1 ^ this.world.getSeed());
BlockFalling.fallInstantly = true;
// Have to regeneate the biomes so that any virtual biomes can be passed to the populator.
this.cachedBiomes.reuse(new Vector3i(chunkX * 16, 0, chunkZ * 16));
this.biomeGenerator.generateBiomes(this.cachedBiomes);
ImmutableBiomeVolume biomeBuffer = this.cachedBiomes.getImmutableBiomeCopy();
BlockPos blockpos = new BlockPos(chunkX * 16, 0, chunkZ * 16);
BiomeType biome = (BiomeType) this.world.getBiome(blockpos.add(16, 0, 16));
Chunk chunk = (Chunk) this.world.getChunkFromChunkCoords(chunkX, chunkZ);
BiomeGenerationSettings settings = getBiomeSettings(biome);
List<Populator> populators = new ArrayList<>(this.pop);
Populator snowPopulator = null;
Iterator<Populator> itr = populators.iterator();
while (itr.hasNext()) {
Populator populator = itr.next();
if (populator instanceof SnowPopulator) {
itr.remove();
snowPopulator = populator;
break;
}
}
populators.addAll(settings.getPopulators());
if (snowPopulator != null) {
populators.add(snowPopulator);
}
Sponge.getGame().getEventManager().post(SpongeEventFactory.createPopulateChunkEventPre(Sponge.getCauseStackManager().getCurrentCause(), populators, chunk));
MinecraftForge.EVENT_BUS.post(new PopulateChunkEvent.Pre(this, this.world, this.rand, chunkX, chunkZ, false));
MinecraftForge.EVENT_BUS.post(new DecorateBiomeEvent.Pre(this.world, this.rand, blockpos));
MinecraftForge.ORE_GEN_BUS.post(new OreGenEvent.Pre(this.world, this.rand, blockpos));
List<String> flags = Lists.newArrayList();
Vector3i min = new Vector3i(chunkX * 16 + 8, 0, chunkZ * 16 + 8);
org.spongepowered.api.world.World spongeWorld = (org.spongepowered.api.world.World) this.world;
Extent volume = new SoftBufferExtentViewDownsize(chunk.getWorld(), min, min.add(15, 255, 15), min.sub(8, 0, 8), min.add(23, 255, 23));
for (Populator populator : populators) {
if (!(populator instanceof PlainsGrassPopulator)) {
if (!this.checkForgeEvent(populator, this, chunkX, chunkZ, flags, chunk)) {
continue;
}
} else {
final PlainsGrassPopulator grassPop = (PlainsGrassPopulator) populator;
if (!this.checkForgeEvent(grassPop.getFlowers(), this, chunkX, chunkZ, flags, chunk)) {
grassPop.setPopulateFlowers(false);
}
if (!this.checkForgeEvent(grassPop.getGrass(), this, chunkX, chunkZ, flags, chunk)) {
grassPop.setPopulateGrass(false);
}
if (!this.checkForgeEvent(grassPop.getPlant(), this, chunkX, chunkZ, flags, chunk)) {
grassPop.setPopulateGrass(false);
}
if (!grassPop.isPopulateFlowers() && !grassPop.isPopulateGrass()) {
continue;
}
}
final PopulatorType type = populator.getType();
if (Sponge.getGame().getEventManager().post(SpongeEventFactory.createPopulateChunkEventPopulate(Sponge.getCauseStackManager().getCurrentCause(), populator, chunk))) {
continue;
}
try (PopulatorPhaseContext context = GenerationPhase.State.POPULATOR_RUNNING.createPhaseContext().world(this.world).populator(type).buildAndSwitch()) {
Timing timing = null;
if (Timings.isTimingsEnabled()) {
timing = this.populatorTimings.get(populator.getType().getId());
if (timing == null) {
timing = SpongeTimingsFactory.ofSafe(populator.getType().getId());
this.populatorTimings.put(populator.getType().getId(), timing);
}
timing.startTimingIfSync();
}
if (populator instanceof IFlaggedPopulator) {
((IFlaggedPopulator) populator).populate(spongeWorld, volume, this.rand, biomeBuffer, flags);
} else {
populator.populate(spongeWorld, volume, this.rand, biomeBuffer);
}
if (Timings.isTimingsEnabled()) {
timing.stopTimingIfSync();
}
}
}
MinecraftForge.ORE_GEN_BUS.post(new OreGenEvent.Post(this.world, this.rand, blockpos));
MinecraftForge.EVENT_BUS.post(new DecorateBiomeEvent.Post(this.world, this.rand, blockpos));
MinecraftForge.EVENT_BUS.post(new PopulateChunkEvent.Post(this, this.world, this.rand, chunkX, chunkZ, false));
// populate method so that its particular changes are used.
if (this.baseGenerator instanceof SpongeGenerationPopulator) {
Timing timing = null;
IChunkGenerator chunkGenerator = ((SpongeGenerationPopulator) this.baseGenerator).getHandle(this.world);
if (Timings.isTimingsEnabled()) {
IGenerationPopulator spongePopulator = (IGenerationPopulator) this.baseGenerator;
timing = spongePopulator.getTimingsHandler();
timing.startTimingIfSync();
}
chunkGenerator.populate(chunkX, chunkZ);
if (Timings.isTimingsEnabled()) {
timing.stopTimingIfSync();
}
}
org.spongepowered.api.event.world.chunk.PopulateChunkEvent.Post event = SpongeEventFactory.createPopulateChunkEventPost(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.copyOf(populators), chunk);
SpongeImpl.postEvent(event);
BlockFalling.fallInstantly = false;
this.chunkGeneratorTiming.stopTimingIfSync();
((IMixinWorldServer) spongeWorld).getTimingsHandler().chunkPopulate.stopTimingIfSync();
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeForge by SpongePowered.
the class MixinItemShears method itemInteractionForEntity.
/**
* @author gabizou - June 21st, 2016
* @reason Rewrites the forge handling of this to properly handle
* when sheared drops are captured by whatever current phase the
* {@link PhaseTracker} is in.
*
* Returns true if the item can be used on the given entity, e.g. shears on sheep.
*/
@Overwrite
@Override
public boolean itemInteractionForEntity(ItemStack itemstack, EntityPlayer player, EntityLivingBase entity, EnumHand hand) {
if (entity.world.isRemote) {
return false;
}
if (entity instanceof IShearable) {
IShearable target = (IShearable) entity;
BlockPos pos = new BlockPos(entity.posX, entity.posY, entity.posZ);
if (target.isShearable(itemstack, entity.world, pos)) {
List<ItemStack> drops = target.onSheared(itemstack, entity.world, pos, EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, itemstack));
// Sponge Start - Handle drops according to the current phase
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData currentData = phaseTracker.getCurrentPhaseData();
final IPhaseState<?> currentState = currentData.state;
final PhaseContext<?> phaseContext = currentData.context;
final Random random = EntityUtil.fromNative(entity).getRandom();
final IMixinEntity mixinEntity = EntityUtil.toMixin(entity);
final double posX = entity.posX;
final double posY = entity.posY + 1.0F;
final double posZ = entity.posZ;
final Vector3d position = new Vector3d(posX, posY, posZ);
// Now the real fun begins.
for (ItemStack drop : drops) {
final ItemStack item;
if (!drop.isEmpty()) {
try (final CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
// FIRST we want to throw the DropItemEvent.PRE
final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(drop);
final List<ItemStackSnapshot> original = new ArrayList<>();
original.add(snapshot);
Sponge.getCauseStackManager().pushCause(entity);
final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of(snapshot), original);
if (dropEvent.isCancelled()) {
continue;
}
// SECOND throw the ConstructEntityEvent
Transform<World> suggested = new Transform<>(mixinEntity.getWorld(), position);
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));
}
} else {
continue;
}
if (item == null) {
continue;
}
if (!item.isEmpty()) {
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).motion(new Vector3d((random.nextFloat() - random.nextFloat()) * 0.1F, random.nextFloat() * 0.05F, (random.nextFloat() - random.nextFloat()) * 0.1F)).position(new Vector3d(posX, posY, posZ)).build());
continue;
}
final List<ItemDropData> itemStacks = phaseContext.getCapturedItemStackSupplier().get();
SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).motion(new Vector3d((random.nextFloat() - random.nextFloat()) * 0.1F, random.nextFloat() * 0.05F, (random.nextFloat() - random.nextFloat()) * 0.1F)).build());
continue;
}
EntityItem entityitem = new EntityItem(entity.world, posX, posY, posZ, item);
entityitem.setDefaultPickupDelay();
entityitem.motionY += random.nextFloat() * 0.05F;
entityitem.motionX += (random.nextFloat() - random.nextFloat()) * 0.1F;
entityitem.motionZ += (random.nextFloat() - random.nextFloat()) * 0.1F;
// 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.
continue;
}
// FINALLY - Spawn the entity in the world if all else didn't fail
entity.world.spawnEntity(entityitem);
}
}
// Sponge End
itemstack.damageItem(1, entity);
}
return true;
}
return false;
}
Aggregations