Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.ryanhcode.sable.api.entity;

import dev.ryanhcode.sable.sublevel.SubLevel;

/**
* Implemented by synthetic interaction entities whose position and rotation
* may already be expressed in a target SubLevel's local coordinate system.
*
* <p>When this returns {@code true}, Sable must not inverse-transform the
* entity into the same SubLevel a second time.</p>
*/
public interface TargetLocalInteractionEntity {

/**
* @param targetSubLevel the SubLevel containing the interaction target
* @return true when this entity is already expressed in the target's
* local coordinate system
*/
boolean sable$isAlreadyLocalTo(SubLevel targetSubLevel);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import dev.ryanhcode.sable.Sable;
import dev.ryanhcode.sable.api.SubLevelHelper;
import dev.ryanhcode.sable.api.entity.TargetLocalInteractionEntity;
import dev.ryanhcode.sable.companion.math.BoundingBox3d;
import dev.ryanhcode.sable.companion.math.BoundingBox3dc;
import dev.ryanhcode.sable.api.math.LevelReusedVectors;
Expand Down Expand Up @@ -40,6 +41,16 @@ public abstract class BlockPlaceContextMixin extends UseOnContext {
@Shadow
protected boolean replaceClicked;

@Unique
private static boolean sable$isAlreadyTargetLocal(
final Entity entity,
final SubLevel targetSubLevel
) {
return entity instanceof
final TargetLocalInteractionEntity localEntity
&& localEntity.sable$isAlreadyLocalTo(targetSubLevel);
}

public BlockPlaceContextMixin(final Player pPlayer, final InteractionHand pHand, final BlockHitResult pHitResult) {
super(pPlayer, pHand, pHitResult);
}
Expand All @@ -51,6 +62,7 @@ public BlockPlaceContextMixin(final Player pPlayer, final InteractionHand pHand,
private Direction sable$getFacingAxis(final Entity player, final Direction.Axis axis) {
final SubLevel subLevel = Sable.HELPER.getContaining(this.getLevel(), this.getClickedPos());

if(subLevel==null||sable$isAlreadyTargetLocal(player, subLevel)) return Direction.getFacingAxis(player,axis);
if (subLevel != null) {
SubLevelHelper.pushEntityLocal(subLevel, player);
final Direction facingAxis = Direction.getFacingAxis(player, axis);
Expand All @@ -65,14 +77,13 @@ public BlockPlaceContextMixin(final Player pPlayer, final InteractionHand pHand,
private Direction[] sable$orderedByNearest(final Entity player) {
final SubLevel subLevel = Sable.HELPER.getContaining(this.getLevel(), this.getClickedPos());

if (subLevel != null) {
SubLevelHelper.pushEntityLocal(subLevel, player);
final Direction[] nearest = Direction.orderedByNearest(player);
SubLevelHelper.popEntityLocal(subLevel, player);
return nearest;
}
if (subLevel == null || sable$isAlreadyTargetLocal(player, subLevel)) return Direction.orderedByNearest(player);

SubLevelHelper.pushEntityLocal(subLevel, player);
final Direction[] nearest = Direction.orderedByNearest(player);
SubLevelHelper.popEntityLocal(subLevel, player);
return nearest;

return Direction.orderedByNearest(player);
}

@Inject(method = "canPlace", at = @At("HEAD"), cancellable = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@

import dev.ryanhcode.sable.Sable;
import dev.ryanhcode.sable.api.SubLevelHelper;
import dev.ryanhcode.sable.api.entity.TargetLocalInteractionEntity;
import dev.ryanhcode.sable.sublevel.SubLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
Expand All @@ -34,18 +37,70 @@ public abstract class UseOnContextMixin {
@Shadow
public abstract BlockPos getClickedPos();

@Unique
private boolean sable$isAlreadyTargetLocal(
final SubLevel targetSubLevel
) {
return this.player instanceof
final TargetLocalInteractionEntity localEntity
&& localEntity.sable$isAlreadyLocalTo(targetSubLevel);
}

@Inject(
method = "getClickedFace",
at = @At("HEAD"),
cancellable = true
)
private void sable$getClickedFace(
final CallbackInfoReturnable<Direction> cir
) {
if (this.player == null)
return;

final SubLevel targetSubLevel =
Sable.HELPER.getContaining(
this.level,
this.getClickedPos()
);

if (targetSubLevel == null)
return;

/*
* Create has already expressed the DeployerFakePlayer's look direction
* in the target SubLevel's local coordinate system.
*/
if (!this.sable$isAlreadyTargetLocal(targetSubLevel))
return;

final Vec3 localLook = this.player.getLookAngle();

/*
* The deployer looks along the ray toward the target. The clicked surface
* normal therefore points in the opposite direction.
*/
final Direction localClickedFace =
Direction.getNearest(
localLook.x,
localLook.y,
localLook.z
).getOpposite();

cir.setReturnValue(localClickedFace);
}

@Inject(method = "getHorizontalDirection", at = @At("HEAD"), cancellable = true)
private void sable$getHorizontalDirection(final CallbackInfoReturnable<Direction> cir) {
if (this.player == null) return;

final SubLevel subLevel = Sable.HELPER.getContaining(this.level, this.getClickedPos());

if (subLevel != null) {
SubLevelHelper.pushEntityLocal(subLevel, this.player);
final Direction dir = this.player.getDirection();
SubLevelHelper.popEntityLocal(subLevel, this.player);
cir.setReturnValue(dir);
}
if (subLevel == null||this.sable$isAlreadyTargetLocal(subLevel)) return;

SubLevelHelper.pushEntityLocal(subLevel, this.player);
final Direction dir = this.player.getDirection();
SubLevelHelper.popEntityLocal(subLevel, this.player);
cir.setReturnValue(dir);
}

@Inject(method = "getRotation", at = @At("HEAD"), cancellable = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dev.ryanhcode.sable.neoforge.mixin.compatibility.create.deployer;

import com.simibubi.create.content.kinetics.deployer.DeployerFakePlayer;
import dev.ryanhcode.sable.Sable;
import dev.ryanhcode.sable.api.entity.TargetLocalInteractionEntity;
import dev.ryanhcode.sable.sublevel.SubLevel;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;

@Mixin(value = DeployerFakePlayer.class, remap = false)
public abstract class DeployerFakePlayerMixin
implements TargetLocalInteractionEntity {

@Override
public boolean sable$isAlreadyLocalTo(
final SubLevel targetSubLevel
) {
final Entity self = (Entity) (Object) this;

/*
* DeployerHandler moves its FakePlayer to the ray origin before
* creating UseOnContext. Inside a Sable SubLevel, this position and
* the rotation supplied by Create are both SubLevel-local.
*/
final SubLevel sourceSubLevel =
Sable.HELPER.getContaining(
self.level(),
self.position()
);

/*
* Both instances originate from Sable's loaded SubLevel registry,
* so identity comparison is intentional.
*/
return sourceSubLevel != null
&& sourceSubLevel == targetSubLevel;
}
}
1 change: 1 addition & 0 deletions neoforge/src/main/resources/sable-neoforge.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"compatibility.create.crushing_wheel.CrushingWheelBlockMixin",
"compatibility.create.crushing_wheel_entity_processing.CrushingWheelControllerBlockEntityMixin",
"compatibility.create.deployer.DeployerBlockEntityMixin",
"compatibility.create.deployer.DeployerFakePlayerMixin",
"compatibility.create.display_link.ClickToLinkBlockItemMixin",
"compatibility.create.display_link.DisplayLinkBlockEntityMixin",
"compatibility.create.display_link.DisplayLinkBlockMixin",
Expand Down