use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.
the class MixinDedicatedServer method isBlockProtected.
/**
* @author zml - March 9th, 2016
* @author blood - July 7th, 2016 - Add cause tracker handling for throwing pre change block checks
* @author gabizou - July 7th, 2016 - Update for 1.10's cause tracking changes
*
* @reason Change spawn protection to take advantage of Sponge permissions. Rather than affecting only the default world like vanilla, this
* will apply to any world. Additionally, fire a spawn protection event
*/
@Overwrite
@Override
public boolean isBlockProtected(net.minecraft.world.World worldIn, BlockPos pos, EntityPlayer playerIn) {
// Mods such as ComputerCraft and Thaumcraft check this method before attempting to set a blockstate.
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData peek = phaseTracker.getCurrentPhaseData();
final IPhaseState phaseState = peek.state;
if (phaseState == null || !phaseState.isInteraction()) {
// TODO BLOCK_PROTECTED flag
if (SpongeCommonEventFactory.callChangeBlockEventPre((IMixinWorldServer) worldIn, pos, playerIn).isCancelled()) {
return true;
}
}
BlockPos spawnPoint = worldIn.getSpawnPoint();
int protectionRadius = getSpawnProtectionSize();
return protectionRadius > 0 && Math.max(Math.abs(pos.getX() - spawnPoint.getX()), Math.abs(pos.getZ() - spawnPoint.getZ())) <= protectionRadius && !((Player) playerIn).hasPermission("minecraft.spawn-protection.override");
}
use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callNotifyNeighborEvent.
@SuppressWarnings("rawtypes")
public static NotifyNeighborBlockEvent callNotifyNeighborEvent(World world, BlockPos sourcePos, EnumSet notifiedSides) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData peek = phaseTracker.getCurrentPhaseData();
final PhaseContext<?> context = peek.context;
// Don't fire notify events during world gen or while restoring
if (peek.state.isWorldGeneration() || peek.state == State.RESTORING_BLOCKS) {
return null;
}
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
final BlockState blockstate = (BlockState) ((net.minecraft.world.World) world).getBlockState(sourcePos);
final LocatableBlock locatable = LocatableBlock.builder().location(new Location<World>(world, sourcePos.getX(), sourcePos.getY(), sourcePos.getZ())).state(blockstate).build();
if (context.getNotifier().isPresent()) {
context.addNotifierAndOwnerToCauseStack();
} else {
final IMixinChunk mixinChunk = (IMixinChunk) ((WorldServer) world).getChunkFromBlockCoords(sourcePos);
mixinChunk.getBlockNotifier(sourcePos).ifPresent(user -> Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, user));
mixinChunk.getBlockOwner(sourcePos).ifPresent(owner -> Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner));
}
Sponge.getCauseStackManager().pushCause(locatable);
final Map<Direction, BlockState> neighbors = new HashMap<>();
for (Object obj : notifiedSides) {
EnumFacing notifiedSide = (EnumFacing) obj;
BlockPos offset = sourcePos.offset(notifiedSide);
Direction direction = DirectionFacingProvider.getInstance().getKey(notifiedSide).get();
Location<World> location = new Location<>(world, VecHelper.toVector3i(offset));
if (location.getBlockY() >= 0 && location.getBlockY() <= 255) {
neighbors.put(direction, location.getBlock());
}
}
// ImmutableMap<Direction, BlockState> originalNeighbors =
// ImmutableMap.copyOf(neighbors);
NotifyNeighborBlockEvent event = SpongeEventFactory.createNotifyNeighborBlockEvent(Sponge.getCauseStackManager().getCurrentCause(), neighbors, neighbors);
SpongeImpl.postEvent(event);
return event;
}
}
use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callChangeBlockEventPre.
/**
* Processes pre block event data then fires event.
*
* Note: This method does not create a stack frame.
* Any caller to this method should have a frame created to
* avoid stack corruption.
*
* @param worldIn The world
* @param locations The locations affected
* @param source The source of event
* @return The event
*/
private static ChangeBlockEvent.Pre callChangeBlockEventPre(IMixinWorldServer worldIn, ImmutableList<Location<World>> locations, @Nullable Object source) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData data = phaseTracker.getCurrentPhaseData();
if (source == null) {
source = data.context.getSource(LocatableBlock.class).orElse(null);
if (source == null) {
// safety measure, return a dummy event
if (DUMMY_BLOCK_PRE_EVENT == null) {
DUMMY_BLOCK_PRE_EVENT = SpongeEventFactory.createChangeBlockEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of());
}
return DUMMY_BLOCK_PRE_EVENT;
}
}
EntityPlayer player = null;
User owner = data.context.getOwner().orElse(null);
User notifier = data.context.getNotifier().orElse(null);
Sponge.getCauseStackManager().pushCause(source);
if (source instanceof Player) {
player = (EntityPlayer) source;
if (SpongeImplHooks.isFakePlayer(player)) {
Sponge.getCauseStackManager().addContext(EventContextKeys.FAKE_PLAYER, EntityUtil.toPlayer(player));
}
}
if (owner != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
} else if (player != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, (User) player);
}
if (notifier != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
}
ChangeBlockEvent.Pre event = SpongeEventFactory.createChangeBlockEventPre(Sponge.getCauseStackManager().getCurrentCause(), locations);
SpongeImpl.postEvent(event);
return event;
}
use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callChangeBlockEventModifyLiquidBreak.
public static ChangeBlockEvent.Break callChangeBlockEventModifyLiquidBreak(net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, int flags) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData data = phaseTracker.getCurrentPhaseData();
BlockState fromState = BlockUtil.fromNative(worldIn.getBlockState(pos));
BlockState toState = BlockUtil.fromNative(state);
User owner = data.context.getOwner().orElse(null);
User notifier = data.context.getNotifier().orElse(null);
Object source = data.context.getSource(LocatableBlock.class).orElse(null);
if (source == null) {
// Fallback
source = worldIn;
}
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(source);
Sponge.getCauseStackManager().addContext(EventContextKeys.LIQUID_BREAK, (World) worldIn);
if (owner != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
}
if (notifier != null) {
Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
}
WorldProperties world = ((World) worldIn).getProperties();
Vector3i position = new Vector3i(pos.getX(), pos.getY(), pos.getZ());
Transaction<BlockSnapshot> transaction = new Transaction<>(BlockSnapshot.builder().blockState(fromState).world(world).position(position).build(), BlockSnapshot.builder().blockState(toState).world(world).position(position).build());
ChangeBlockEvent.Break event = SpongeEventFactory.createChangeBlockEventBreak(Sponge.getCauseStackManager().getCurrentCause(), Collections.singletonList(transaction));
SpongeImpl.postEvent(event);
return event;
}
}
use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.
the class ContainerUtil method performBlockInventoryDrops.
/**
* Replacement helper method for {@link MixinInventoryHelper#spongeDropInventoryItems(World, double, double, double, IInventory)}
* to perform cause tracking related drops. This is specific for blocks, not for any other cases.
*
* @param worldServer The world server
* @param x the x position
* @param y the y position
* @param z the z position
* @param inventory The inventory to drop items from
*/
public static void performBlockInventoryDrops(WorldServer worldServer, double x, double y, double z, IInventory inventory) {
final PhaseData currentPhase = PhaseTracker.getInstance().getCurrentPhaseData();
final IPhaseState currentState = currentPhase.state;
if (currentState.tracksBlockSpecificDrops()) {
final PhaseContext<?> context = currentPhase.context;
if (!currentState.ignoresItemPreMerging() && SpongeImpl.getGlobalConfig().getConfig().getOptimizations().doDropsPreMergeItemDrops()) {
// Add itemstack to pre merge list
final Multimap<BlockPos, ItemDropData> multimap = context.getBlockDropSupplier().get();
final BlockPos pos = new BlockPos(x, y, z);
final Collection<ItemDropData> itemStacks = multimap.get(pos);
for (int i = 0; i < inventory.getSizeInventory(); i++) {
final net.minecraft.item.ItemStack itemStack = inventory.getStackInSlot(i);
if (!itemStack.isEmpty()) {
SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(itemStack).position(VecHelper.toVector3d(pos)).build());
}
}
} else {
// Don't do pre-merging - directly spawn in item
final Multimap<BlockPos, EntityItem> multimap = context.getBlockItemDropSupplier().get();
final BlockPos pos = new BlockPos(x, y, z);
final Collection<EntityItem> itemStacks = multimap.get(pos);
for (int j = 0; j < inventory.getSizeInventory(); j++) {
final net.minecraft.item.ItemStack itemStack = inventory.getStackInSlot(j);
if (!itemStack.isEmpty()) {
float f = RANDOM.nextFloat() * 0.8F + 0.1F;
float f1 = RANDOM.nextFloat() * 0.8F + 0.1F;
float f2 = RANDOM.nextFloat() * 0.8F + 0.1F;
while (!itemStack.isEmpty()) {
int i = RANDOM.nextInt(21) + 10;
EntityItem entityitem = new EntityItem(worldServer, x + f, y + f1, z + f2, itemStack.splitStack(i));
entityitem.motionX = RANDOM.nextGaussian() * 0.05;
entityitem.motionY = RANDOM.nextGaussian() * 0.05 + 0.2;
entityitem.motionZ = RANDOM.nextGaussian() * 0.05;
itemStacks.add(entityitem);
}
}
}
}
return;
}
// Finally, just default to spawning the entities normally, regardless of the case.
for (int i = 0; i < inventory.getSizeInventory(); i++) {
final net.minecraft.item.ItemStack itemStack = inventory.getStackInSlot(i);
if (!itemStack.isEmpty()) {
InventoryHelper.spawnItemStack(worldServer, x, y, z, itemStack);
}
}
}
Aggregations