use of org.spongepowered.common.block.SpongeBlockSnapshot in project SpongeCommon by SpongePowered.
the class TransactionSink method logBlockDrops.
@SuppressWarnings("ConstantConditions")
default EffectTransactor logBlockDrops(final Level serverWorld, final BlockPos pos, final BlockState state, @Nullable final BlockEntity tileEntity) {
final WeakReference<ServerLevel> worldRef = new WeakReference<>((ServerLevel) serverWorld);
final Supplier<ServerLevel> worldSupplier = () -> Objects.requireNonNull(worldRef.get(), "ServerWorld dereferenced");
final SpongeBlockSnapshot original = TrackingUtil.createPooledSnapshot(state, pos, BlockChangeFlags.NONE, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT, tileEntity, worldSupplier, Optional::empty, Optional::empty);
original.blockChange = BlockChange.MODIFY;
final PrepareBlockDropsTransaction transaction = new PrepareBlockDropsTransaction(pos, state, original);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(PrepareBlockDrops.getInstance()));
}
use of org.spongepowered.common.block.SpongeBlockSnapshot in project SpongeCommon by SpongePowered.
the class BlockEventBasedTransaction method generateEvent.
@Override
public final Optional<ChangeBlockEvent.All> generateEvent(final PhaseContext<@NonNull ?> context, @Nullable final GameTransaction<@NonNull ?> parent, final ImmutableList<GameTransaction<ChangeBlockEvent.All>> transactions, final Cause currentCause) {
final Optional<ServerWorld> o = ((SpongeServer) SpongeCommon.server()).worldManager().world(this.worldKey);
if (!o.isPresent()) {
return Optional.empty();
}
final ListMultimap<BlockPos, SpongeBlockSnapshot> positions = LinkedListMultimap.create();
for (final GameTransaction<@NonNull ?> transaction : transactions) {
final BlockEventBasedTransaction blockTransaction = (BlockEventBasedTransaction) transaction;
if (!positions.containsKey(blockTransaction.affectedPosition)) {
positions.put(blockTransaction.affectedPosition, blockTransaction.getOriginalSnapshot());
}
if (blockTransaction.getResultingSnapshot() != null) {
positions.put(blockTransaction.affectedPosition, blockTransaction.getResultingSnapshot());
}
}
final ImmutableList<BlockTransaction> eventTransactions = positions.asMap().values().stream().map(spongeBlockSnapshots -> {
final List<SpongeBlockSnapshot> snapshots = new ArrayList<>(spongeBlockSnapshots);
if (snapshots.isEmpty() || snapshots.size() < 2) {
// Error case
return Optional.<BlockTransaction>empty();
}
final SpongeBlockSnapshot original = snapshots.get(0);
final SpongeBlockSnapshot result = snapshots.get(snapshots.size() - 1);
final ImmutableList<BlockSnapshot> intermediary;
if (snapshots.size() > 2) {
intermediary = ImmutableList.copyOf(snapshots.subList(1, snapshots.size() - 2));
} else {
intermediary = ImmutableList.of();
}
final Operation operation = context.getBlockOperation(original, result);
final BlockTransaction eventTransaction = new BlockTransaction(original, result, intermediary, operation);
return Optional.of(eventTransaction);
}).filter(Optional::isPresent).map(Optional::get).collect(ImmutableList.toImmutableList());
if (eventTransactions.isEmpty()) {
return Optional.empty();
}
return Optional.of(SpongeEventFactory.createChangeBlockEventAll(currentCause, eventTransactions, o.get()));
}
use of org.spongepowered.common.block.SpongeBlockSnapshot in project SpongeCommon by SpongePowered.
the class RemoveBlockEntity method captureState.
@Override
protected void captureState() {
super.captureState();
final SpongeBlockSnapshot snapshot = TrackingUtil.createPooledSnapshot(this.originalState, this.affectedPosition, BlockChangeFlags.NONE, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT, this.removed, this.levelSupplier, Optional::empty, Optional::empty);
snapshot.blockChange = BlockChange.MODIFY;
this.tileSnapshot = snapshot;
}
use of org.spongepowered.common.block.SpongeBlockSnapshot in project SpongeCommon by SpongePowered.
the class TrackingUtil method associateTrackerToTarget.
public static void associateTrackerToTarget(final BlockChange blockChange, final BlockTransactionReceipt receipt, final UUID uuid) {
final BlockSnapshot finalSnapshot = receipt.finalBlock();
final SpongeBlockSnapshot spongeSnapshot = (SpongeBlockSnapshot) finalSnapshot;
final BlockPos pos = spongeSnapshot.getBlockPos();
final Block block = ((net.minecraft.world.level.block.state.BlockState) spongeSnapshot.state()).getBlock();
spongeSnapshot.getServerWorld().map(world -> world.getChunkAt(pos)).map(chunk -> (LevelChunkBridge) chunk).ifPresent(spongeChunk -> {
final PlayerTracker.Type trackerType = blockChange == BlockChange.PLACE ? PlayerTracker.Type.CREATOR : PlayerTracker.Type.NOTIFIER;
spongeChunk.bridge$addTrackedBlockPosition(block, pos, uuid, trackerType);
});
}
use of org.spongepowered.common.block.SpongeBlockSnapshot in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method bridge$createSnapshot.
@Override
public SpongeBlockSnapshot bridge$createSnapshot(final net.minecraft.world.level.block.state.BlockState state, final BlockPos pos, final BlockChangeFlag updateFlag) {
final SpongeBlockSnapshot.BuilderImpl builder = SpongeBlockSnapshot.BuilderImpl.pooled();
builder.reset();
builder.blockState(state).world((ServerLevel) (Object) this).position(VecHelper.toVector3i(pos));
final LevelChunk chunk = this.shadow$getChunkAt(pos);
if (chunk == null) {
return builder.flag(updateFlag).build();
}
final Optional<UUID> creator = ((LevelChunkBridge) chunk).bridge$getBlockCreatorUUID(pos);
final Optional<UUID> notifier = ((LevelChunkBridge) chunk).bridge$getBlockNotifierUUID(pos);
creator.ifPresent(builder::creator);
notifier.ifPresent(builder::notifier);
final boolean hasTileEntity = ((BlockStateBridge) state).bridge$hasTileEntity();
final net.minecraft.world.level.block.entity.BlockEntity tileEntity = chunk.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK);
if (hasTileEntity || tileEntity != null) {
// We MUST only check to see if a TE exists to avoid creating a new one.
if (tileEntity != null) {
// TODO - custom data.
final CompoundTag nbt = new CompoundTag();
// Some mods like OpenComputers assert if attempting to save robot while moving
try {
tileEntity.save(nbt);
builder.addUnsafeCompound(nbt);
} catch (final Throwable t) {
// ignore
}
}
}
builder.flag(updateFlag);
return builder.build();
}
Aggregations