use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.
the class MixinTeleporter method findPortal.
@Override
public Optional<Location<World>> findPortal(Location<World> searchLocation) {
double closest = -1.0D;
boolean addToCache = true;
BlockPos portalPosition = BlockPos.ORIGIN;
// Sponge - use the chunk coords instead of block coords
Vector3i chunkPosition = searchLocation.getChunkPosition();
long targetPosition = ChunkPos.asLong(chunkPosition.getX(), chunkPosition.getZ());
if (this.destinationCoordinateCache.containsKey(targetPosition)) {
Teleporter.PortalPosition teleporter$portalposition = this.destinationCoordinateCache.get(targetPosition);
closest = 0.0D;
portalPosition = teleporter$portalposition;
teleporter$portalposition.lastUpdateTime = this.world.getTotalWorldTime();
addToCache = false;
} else {
BlockPos blockSearchPosition = ((IMixinLocation) (Object) searchLocation).getBlockPos();
for (int i1 = -this.searchRadius; i1 <= this.searchRadius; ++i1) {
BlockPos blockpos2;
for (int j1 = -this.searchRadius; j1 <= this.searchRadius; ++j1) {
for (BlockPos blockpos1 = blockSearchPosition.add(i1, this.world.getActualHeight() - 1 - blockSearchPosition.getY(), j1); blockpos1.getY() >= 0; blockpos1 = blockpos2) {
blockpos2 = blockpos1.down();
if (this.world.getBlockState(blockpos1).getBlock() == Blocks.PORTAL) {
while (this.world.getBlockState(blockpos2 = blockpos1.down()).getBlock() == Blocks.PORTAL) {
blockpos1 = blockpos2;
}
double distance = blockpos1.distanceSq(blockSearchPosition);
if (closest < 0.0D || distance < closest) {
closest = distance;
portalPosition = blockpos1;
}
}
}
}
}
}
if (closest >= 0.0D) {
if (addToCache) {
this.destinationCoordinateCache.put(targetPosition, ((Teleporter) (Object) this).new PortalPosition(portalPosition, this.world.getTotalWorldTime()));
}
return Optional.of(new Location<World>(searchLocation.getExtent(), VecHelper.toVector3d(portalPosition)));
}
return Optional.empty();
}
use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.
the class MixinTeleporter method handleEntityPortalExit.
private void handleEntityPortalExit(Entity entityIn, Location<World> portalLocation, float rotationYaw) {
BlockPos blockPos = ((IMixinLocation) (Object) portalLocation).getBlockPos();
double xTarget = portalLocation.getX() + 0.5D;
double yTarget = portalLocation.getY() + 0.5D;
double zTarget = portalLocation.getZ() + 0.5D;
BlockPattern.PatternHelper blockpattern$patternhelper = Blocks.PORTAL.createPatternHelper(this.world, blockPos);
boolean flag1 = blockpattern$patternhelper.getForwards().rotateY().getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE;
double d2 = blockpattern$patternhelper.getForwards().getAxis() == EnumFacing.Axis.X ? (double) blockpattern$patternhelper.getFrontTopLeft().getZ() : (double) blockpattern$patternhelper.getFrontTopLeft().getX();
yTarget = blockpattern$patternhelper.getFrontTopLeft().getY() + 1 - entityIn.getLastPortalVec().y * blockpattern$patternhelper.getHeight();
if (flag1) {
++d2;
}
if (blockpattern$patternhelper.getForwards().getAxis() == EnumFacing.Axis.X) {
zTarget = d2 + (1.0D - entityIn.getLastPortalVec().x) * blockpattern$patternhelper.getWidth() * blockpattern$patternhelper.getForwards().rotateY().getAxisDirection().getOffset();
} else {
xTarget = d2 + (1.0D - entityIn.getLastPortalVec().x) * blockpattern$patternhelper.getWidth() * blockpattern$patternhelper.getForwards().rotateY().getAxisDirection().getOffset();
}
float f = 0.0F;
float f1 = 0.0F;
float f2 = 0.0F;
float f3 = 0.0F;
if (blockpattern$patternhelper.getForwards().getOpposite() == entityIn.getTeleportDirection()) {
f = 1.0F;
f1 = 1.0F;
} else if (blockpattern$patternhelper.getForwards().getOpposite() == entityIn.getTeleportDirection().getOpposite()) {
f = -1.0F;
f1 = -1.0F;
} else if (blockpattern$patternhelper.getForwards().getOpposite() == entityIn.getTeleportDirection().rotateY()) {
f2 = 1.0F;
f3 = -1.0F;
} else {
f2 = -1.0F;
f3 = 1.0F;
}
double d3 = entityIn.motionX;
double d4 = entityIn.motionZ;
entityIn.motionX = d3 * f + d4 * f3;
entityIn.motionZ = d3 * f2 + d4 * f1;
entityIn.rotationYaw = rotationYaw - entityIn.getTeleportDirection().getOpposite().getHorizontalIndex() * 90 + blockpattern$patternhelper.getForwards().getHorizontalIndex() * 90;
entityIn.setLocationAndAngles(xTarget, yTarget, zTarget, entityIn.rotationYaw, entityIn.rotationPitch);
}
use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.
the class RandomBlockPopulator method populate.
@Override
public void populate(org.spongepowered.api.world.World world, Extent extent, Random random) {
Vector3i min = extent.getBlockMin();
Vector3i size = extent.getBlockSize();
int n = this.count.getFlooredAmount(random);
Location<World> chunkMin = new Location<World>(world, min.getX(), min.getY(), min.getZ());
for (int i = 0; i < n; i++) {
Location<World> pos = chunkMin.add(random.nextInt(size.getX()), this.height.getFlooredAmount(random), random.nextInt(size.getZ()));
if (this.check.test(pos)) {
world.setBlock(pos.getBlockPosition(), this.state);
// Liquids force a block update tick so they may flow during world gen
try {
((WorldServer) world).immediateBlockTick(((IMixinLocation) (Object) pos).getBlockPos(), (IBlockState) this.state, random);
} catch (IllegalArgumentException e) {
// ignore
}
}
}
}
use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeForge by SpongePowered.
the class SpongeForgeEventFactory method callNeighborNotifyEvent.
public static NotifyNeighborBlockEvent callNeighborNotifyEvent(Event event) {
NotifyNeighborBlockEvent spongeEvent = (NotifyNeighborBlockEvent) event;
LocatableBlock locatableBlock = spongeEvent.getCause().first(LocatableBlock.class).orElse(null);
TileEntity tileEntitySource = spongeEvent.getCause().first(TileEntity.class).orElse(null);
Location<World> sourceLocation = null;
IBlockState state = null;
if (locatableBlock != null) {
Location<World> location = locatableBlock.getLocation();
sourceLocation = location;
state = (IBlockState) locatableBlock.getBlockState();
} else if (tileEntitySource != null) {
sourceLocation = tileEntitySource.getLocation();
state = (IBlockState) sourceLocation.getBlock();
} else {
// should never happen but just in case it does
return spongeEvent;
}
EnumSet<EnumFacing> facings = EnumSet.noneOf(EnumFacing.class);
for (Map.Entry<Direction, BlockState> mapEntry : spongeEvent.getNeighbors().entrySet()) {
if (mapEntry.getKey() != Direction.NONE) {
facings.add(DirectionFacingProvider.getInstance().get(mapEntry.getKey()).get());
}
}
if (facings.isEmpty()) {
return spongeEvent;
}
BlockPos pos = ((IMixinLocation) (Object) sourceLocation).getBlockPos();
net.minecraft.world.World world = (net.minecraft.world.World) sourceLocation.getExtent();
// TODO - the boolean forced redstone bit needs to be set properly
final NeighborNotifyEvent forgeEvent = new NeighborNotifyEvent(world, pos, state, facings, false);
((IMixinEventBus) MinecraftForge.EVENT_BUS).post(forgeEvent, true);
if (forgeEvent.isCanceled()) {
spongeEvent.setCancelled(true);
}
return spongeEvent;
}
use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.
the class TrackingUtil method processBlockCaptures.
/**
* Processes the given list of {@link BlockSnapshot}s and creates and throws and processes
* the {@link ChangeBlockEvent}s as appropriately determined based on the {@link BlockChange}
* for each snapshot. If any transactions are invalid or events cancelled, this event
* returns {@code false} to signify a transaction was cancelled. This return value
* is used for portal creation.
*
* @param snapshots The snapshots to process
* @param state The phase state that is being processed, used to handle marking notifiers
* and block owners
* @param context The phase context, only used by the phase for handling processes.
* @return True if no events or transactions were cancelled
*/
@SuppressWarnings({ "unchecked" })
public static boolean processBlockCaptures(List<BlockSnapshot> snapshots, IPhaseState<?> state, PhaseContext<?> context) {
if (snapshots.isEmpty()) {
return false;
}
ImmutableList<Transaction<BlockSnapshot>>[] transactionArrays = new ImmutableList[EVENT_COUNT];
ImmutableList.Builder<Transaction<BlockSnapshot>>[] transactionBuilders = new ImmutableList.Builder[EVENT_COUNT];
for (int i = 0; i < EVENT_COUNT; i++) {
transactionBuilders[i] = new ImmutableList.Builder<>();
}
final List<ChangeBlockEvent> blockEvents = new ArrayList<>();
for (BlockSnapshot snapshot : snapshots) {
// This processes each snapshot to assign them to the correct event in the next area, with the
// correct builder array entry.
TRANSACTION_PROCESSOR.apply(transactionBuilders).accept(TRANSACTION_CREATION.apply(snapshot));
}
for (int i = 0; i < EVENT_COUNT; i++) {
// Build each event array
transactionArrays[i] = transactionBuilders[i].build();
}
// Clear captured snapshots after processing them
context.getCapturedBlocksOrEmptyList().clear();
final ChangeBlockEvent[] mainEvents = new ChangeBlockEvent[BlockChange.values().length];
// case in point for WorldTick event listeners since the players are captured non-deterministically
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
if (context.getNotifier().isPresent()) {
Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, context.getNotifier().get());
}
if (context.getOwner().isPresent()) {
Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, context.getOwner().get());
}
try {
state.associateAdditionalCauses(state, context);
} catch (Exception e) {
// TODO - this should be a thing to associate additional objects in the cause, or context, but for now it's just a simple
// try catch to avoid bombing on performing block changes.
}
// Creates the block events accordingly to the transaction arrays
// Needs to throw events
iterateChangeBlockEvents(transactionArrays, blockEvents, mainEvents);
// We create the post event and of course post it in the method, regardless whether any transactions are invalidated or not
final ChangeBlockEvent.Post postEvent = throwMultiEventsAndCreatePost(transactionArrays, blockEvents, mainEvents);
if (postEvent == null) {
// Means that we have had no actual block changes apparently?
return false;
}
final List<Transaction<BlockSnapshot>> invalid = new ArrayList<>();
boolean noCancelledTransactions = true;
// transactions of the preceeding block events)
for (ChangeBlockEvent blockEvent : blockEvents) {
// Need to only check if the event is cancelled, If it is, restore
if (blockEvent.isCancelled()) {
noCancelledTransactions = false;
// Don't restore the transactions just yet, since we're just marking them as invalid for now
for (Transaction<BlockSnapshot> transaction : Lists.reverse(blockEvent.getTransactions())) {
transaction.setValid(false);
}
}
}
// Finally check the post event
if (postEvent.isCancelled()) {
// Of course, if post is cancelled, just mark all transactions as invalid.
noCancelledTransactions = false;
for (Transaction<BlockSnapshot> transaction : postEvent.getTransactions()) {
transaction.setValid(false);
}
}
// Because after, we will restore all the invalid transactions in reverse order.
for (Transaction<BlockSnapshot> transaction : postEvent.getTransactions()) {
if (!transaction.isValid()) {
invalid.add(transaction);
// Cancel any block drops performed, avoids any item drops, regardless
final Location<World> location = transaction.getOriginal().getLocation().orElse(null);
if (location != null) {
final BlockPos pos = ((IMixinLocation) (Object) location).getBlockPos();
context.getBlockItemDropSupplier().removeAllIfNotEmpty(pos);
context.getBlockEntitySpawnSupplier().removeAllIfNotEmpty(pos);
context.getBlockEntitySpawnSupplier().removeAllIfNotEmpty(pos);
}
}
}
if (!invalid.isEmpty()) {
// We need to set this value and return it to signify that some transactions were cancelled
noCancelledTransactions = false;
// or the events were cancelled), again in reverse order of which they were received.
for (Transaction<BlockSnapshot> transaction : Lists.reverse(invalid)) {
transaction.getOriginal().restore(true, BlockChangeFlags.NONE);
if (state.tracksBlockSpecificDrops()) {
// Cancel any block drops or harvests for the block change.
// This prevents unnecessary spawns.
final Location<World> location = transaction.getOriginal().getLocation().orElse(null);
if (location != null) {
final BlockPos pos = ((IMixinLocation) (Object) location).getBlockPos();
context.getBlockDropSupplier().removeAllIfNotEmpty(pos);
}
}
}
}
return performBlockAdditions(postEvent.getTransactions(), state, context, noCancelledTransactions);
}
}
Aggregations