From eac19c84e2fe89f73e277e1383f3c164c7433829 Mon Sep 17 00:00:00 2001 From: FlamingAssembler <34496536+Endalion@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:12:22 +0800 Subject: [PATCH] Fix Create Schematic placement, rendering on ships (#690) * initial ugly schematic mixins * added javadoc descriptions for the mixins * Fix the other operations and clean up 6 months is a long time huh --------- Co-authored-by: ewoudje <7384674+ewoudje@users.noreply.github.com> --- .../create/client/MixinDeployTool.java | 67 ++++++++++++++++++ .../create/client/MixinSchematicToolBase.java | 70 +++++++++++++++++++ .../client/MixinSchematicTransformation.java | 57 +++++++++++++++ .../valkyrienskies-common.mixins.json | 3 + 4 files changed, 197 insertions(+) create mode 100644 common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinDeployTool.java create mode 100644 common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSchematicToolBase.java create mode 100644 common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSchematicTransformation.java diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinDeployTool.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinDeployTool.java new file mode 100644 index 000000000..f10487ac3 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinDeployTool.java @@ -0,0 +1,67 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.schematics.client.tools.DeployTool; +import com.simibubi.create.content.schematics.client.tools.SchematicToolBase; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSClientGameUtils; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +/** + * DeployTool is responsible for the render transform of the placement bounding box (not the preview) + *
+ * Create applies both the camera and bounding-box position in the same PoseStack operation,
+ * the latter of which does not respect ship-space.
+ * This mixin cancels the aforementioned operation and injects the fix in front.
+ */
+@Mixin(value={DeployTool.class})
+public abstract class MixinDeployTool extends SchematicToolBase {
+ @Redirect(
+ method = "renderTool(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/simibubi/create/foundation/render/SuperRenderTypeBuffer;Lnet/minecraft/world/phys/Vec3;)V",
+ at = @At(
+ value = "INVOKE",
+ target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(DDD)V",
+ ordinal = 0
+ )
+ )
+ private void redirectTranslate(PoseStack ms, double _x, double _y, double _z) {
+ }
+
+ @Inject(
+ method = "renderTool(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/simibubi/create/foundation/render/SuperRenderTypeBuffer;Lnet/minecraft/world/phys/Vec3;)V",
+ at = @At(
+ value = "INVOKE",
+ target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(DDD)V",
+ ordinal = 0
+ )
+ )
+ private void mixinRenderTool(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera, CallbackInfo ci) {
+ float pt = AnimationTickHolder.getPartialTicks();
+ double x = Mth.lerp(pt, lastChasingSelectedPos.x, chasingSelectedPos.x);
+ double y = Mth.lerp(pt, lastChasingSelectedPos.y, chasingSelectedPos.y);
+ double z = Mth.lerp(pt, lastChasingSelectedPos.z, chasingSelectedPos.z);
+ Ship ship = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, x, y, z);
+
+ AABB bounds = schematicHandler.getBounds();
+ Vec3 center = bounds.getCenter();
+ int centerX = (int) center.x;
+ int centerZ = (int) center.z;
+
+ if (ship != null) {
+ VSClientGameUtils.transformRenderWithShip(ship.getTransform(), ms, x - centerX, y, z - centerZ, camera.x, camera.y, camera.z);
+ } else {
+ ms.translate(x - centerX - camera.x, y - camera.y, z - centerZ - camera.z);
+ }
+ }
+}
diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSchematicToolBase.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSchematicToolBase.java
new file mode 100644
index 000000000..32a196e4e
--- /dev/null
+++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSchematicToolBase.java
@@ -0,0 +1,70 @@
+package org.valkyrienskies.mod.mixin.mod_compat.create.client;
+
+import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toJOML;
+import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toMinecraft;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+import com.simibubi.create.content.schematics.client.SchematicTransformation;
+import com.simibubi.create.content.schematics.client.tools.SchematicToolBase;
+import net.minecraft.client.Minecraft;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.phys.BlockHitResult;
+import net.minecraft.world.phys.Vec3;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+import org.valkyrienskies.core.api.ships.Ship;
+import org.valkyrienskies.mod.common.VSGameUtilsKt;
+
+/**
+ * SchematicToolBase is responsible for the placement position of the schematic.
+ */
+@Mixin(value={SchematicToolBase.class})
+public abstract class MixinSchematicToolBase {
+ /**
+ * Create uses HitResult::getLocation to get the schematic placement position, which doesn't respect ship-space.
+ * This mixin conditionally changes it to BlockHitResult::getBlockPos instead which *does* respect ship-space.
+ * The original behaviour is otherwise not changed.
+ */
+ @Redirect(
+ method = "updateTargetPos()V",
+ at = @At(
+ value = "INVOKE",
+ target = "Lnet/minecraft/world/phys/BlockHitResult;getLocation()Lnet/minecraft/world/phys/Vec3;",
+ ordinal = 0
+ )
+ )
+ public Vec3 redirectGetLocation(BlockHitResult instance) {
+ BlockPos b = instance.getBlockPos();
+ Ship ship = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, b);
+ if (ship != null) {
+ // The return value is used to form a BlockPos,
+ // so the vec position within a block should not make a difference
+ return Vec3.atLowerCornerOf(b);
+ } else {
+ return instance.getLocation();
+ }
+ }
+
+ /**
+ * Create chose to... uh... evaluate the player look in the local space of the transform. That means we need to
+ * mixin toLocalSpace and transform the player position to the ship-space this schematic is on.
+ * The original behaviour is otherwise not changed.
+ */
+ @WrapOperation(
+ method = "updateTargetPos",
+ at = @At(
+ value = "INVOKE",
+ target = "Lcom/simibubi/create/content/schematics/client/SchematicTransformation;toLocalSpace(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;"
+ )
+ )
+ public Vec3 wrapLocalSpaceToShip(SchematicTransformation transformation, Vec3 vec, Operation
+ * Create applies both the camera and schematic positions in the same operation, the latter of which does not respect ship-space.
+ * This mixin redirects the operation and fixes it by extracting the position components from the argument.
+ * I can't think of a better way to get around it.
+ */
+@Mixin(value = {SchematicTransformation.class}, remap = false)
+public abstract class MixinSchematicTransformation {
+ @Shadow
+ private BlockPos target;
+ @Shadow
+ private Vec3 chasingPos;
+ @Shadow
+ private Vec3 prevChasingPos;
+
+ @Redirect(
+ method = {"applyTransformations(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/phys/Vec3;)V"},
+ at = @At(
+ value = "INVOKE",
+ target = "Lcom/jozufozu/flywheel/util/transform/TransformStack;translate(Lnet/minecraft/world/phys/Vec3;)Ljava/lang/Object;",
+ ordinal = 0
+ )
+ )
+ private Object redirectTranslate(TransformStack instance, Vec3 orig) {
+ PoseStack ms = (PoseStack)instance;
+ Ship ship = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, target.getX(), target.getY(), target.getZ());
+
+ if (ship != null) {
+ float pt = AnimationTickHolder.getPartialTicks();
+ Vec3 pos = VecHelper.lerp(pt, prevChasingPos, chasingPos);
+ Vec3 camera = pos.subtract(orig);
+ VSClientGameUtils.transformRenderWithShip(ship.getTransform(), ms, pos.x, pos.y, pos.z, camera.x, camera.y, camera.z);
+ return instance;
+ } else {
+ return instance.translate(orig);
+ }
+ }
+}
diff --git a/common/src/main/resources/valkyrienskies-common.mixins.json b/common/src/main/resources/valkyrienskies-common.mixins.json
index 3260c9970..152af005d 100644
--- a/common/src/main/resources/valkyrienskies-common.mixins.json
+++ b/common/src/main/resources/valkyrienskies-common.mixins.json
@@ -166,6 +166,9 @@
"mod_compat.create.client.MixinSoundScapes",
"mod_compat.create.client.MixinTileEntityRenderHelper",
"mod_compat.create.client.MixinTrainRelocator",
+ "mod_compat.create.client.MixinDeployTool",
+ "mod_compat.create.client.MixinSchematicToolBase",
+ "mod_compat.create.client.MixinSchematicTransformation",
"mod_compat.create.client.trackOutlines.MixinBigOutlines",
"mod_compat.create.client.MixinValueBox",
"mod_compat.flywheel.InstancingEngineAccessor",