diff --git a/buildSrc/src/main/groovy/multiloader-common.gradle b/buildSrc/src/main/groovy/multiloader-common.gradle index e1c47c26..0ac84302 100644 --- a/buildSrc/src/main/groovy/multiloader-common.gradle +++ b/buildSrc/src/main/groovy/multiloader-common.gradle @@ -48,6 +48,19 @@ repositories { maven { url = "https://maven.ithundxr.dev/snapshots" } // Registrate maven { url = "https://maven.createmod.net" } // Ponder + //oritech + maven { + name = 'GeckoLib' + url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' + content { + includeGroup("software.bernie.geckolib") + } + } + maven { url = 'https://maven.wispforest.io/releases/' } + maven { url = "https://maven.teamresourceful.com/repository/maven-public/" } + maven { url = "https://maven.architectury.dev/" } + // + exclusiveContent { forRepository { maven { diff --git a/common/build.gradle b/common/build.gradle index c201d131..b7e1c71f 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -254,6 +254,8 @@ dependencies { transitive = false } + compileOnly "rearth.oritech:oritech-common-${project.minecraft_version}:${project.oritech_version}" + implementation "fuzs.forgeconfigapiport:forgeconfigapiport-common-neoforgeapi:${forgeconfigapiport_version}" //source: https://github.com/Fuzss/forgeconfigapiport } diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/LaserArmBlockEntityMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/LaserArmBlockEntityMixin.java new file mode 100644 index 00000000..44f4eac4 --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/LaserArmBlockEntityMixin.java @@ -0,0 +1,151 @@ +package dev.ryanhcode.sable.mixin.compatibility.oritech; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import dev.ryanhcode.sable.Sable; +import dev.ryanhcode.sable.companion.math.BoundingBox3d; +import dev.ryanhcode.sable.sublevel.SubLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import rearth.oritech.api.energy.containers.DynamicEnergyStorage; +import rearth.oritech.api.networking.NetworkedBlockEntity; +import rearth.oritech.block.entity.interaction.LaserArmBlockEntity; + +import java.util.ArrayDeque; + +@Mixin(LaserArmBlockEntity.class) +public abstract class LaserArmBlockEntityMixin extends NetworkedBlockEntity { + + @Shadow + protected abstract boolean validTarget(LivingEntity entity); + + @Shadow + private BlockPos targetDirection; + + @Shadow + public abstract BlockPos getLaserHeadPosition(); + + @Shadow + protected abstract ArrayDeque findNextAreaBlockTarget(BlockPos center, int scanDist); + + @Shadow + @Final + protected DynamicEnergyStorage energyStorage; + + public LaserArmBlockEntityMixin(final BlockEntityType type, final BlockPos pos, final BlockState state) { + super(type, pos, state); + } + + @Redirect(method = "trySetNewTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;distManhattan(Lnet/minecraft/core/Vec3i;)I")) + private int test2(final BlockPos instance, final Vec3i vec3i) { + Vec3 centerTarget = Vec3.atCenterOf(vec3i); + Vec3 centerParent = instance.getCenter(); + + centerTarget = Sable.HELPER.projectOutOfSubLevel(this.getLevel(), centerTarget); + centerParent = Sable.HELPER.projectOutOfSubLevel(this.getLevel(), centerParent); + + return BlockPos.containing(centerTarget).distManhattan(BlockPos.containing(centerParent)); + } + + @Redirect(method = "findNextBlockBreakTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;distanceTo(Lnet/minecraft/world/phys/Vec3;)D")) + private double test4(final Vec3 instance, final Vec3 vec) { + return Math.sqrt(Sable.HELPER.distanceSquaredWithSubLevels(this.getLevel(), instance, vec)); + } + +// @Redirect(method = "findNextBlockBreakTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;subtract(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/core/BlockPos;")) +// private BlockPos test3(BlockPos instance, Vec3i vector) { +// instance = BlockPos.containing(Sable.HELPER.projectOutOfSubLevel(this.getLevel(), Vec3.atCenterOf(instance))); +// vector = BlockPos.containing(Sable.HELPER.projectOutOfSubLevel(this.getLevel(), Vec3.atCenterOf(vector))); +// +// return instance.subtract(vector); +// } + + /** + * soft overwrite to use center positions instead of block based positions + */ + //TODO ensure this won't cause issues with other addons that *might* mixin into this call. + @WrapOperation(method = "findNextBlockBreakTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;atLowerCornerOf(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 sable$softOverwriteDirection(final Vec3i toCopy, final Operation original) { + Vec3 centerTargetPos = this.targetDirection.getCenter(); + final SubLevel targetSublevel = Sable.HELPER.getContaining(this.getLevel(), centerTargetPos); + if (targetSublevel != null) { + centerTargetPos = targetSublevel.logicalPose().transformPosition(centerTargetPos); + } + + final Vec3 centerHeadPos = this.getLaserHeadPosition().getCenter(); + final SubLevel parentSublevel = Sable.HELPER.getContaining(this.getLevel(), centerHeadPos); + if (parentSublevel != null) { + centerTargetPos = parentSublevel.logicalPose().transformPositionInverse(centerTargetPos); + } + + //ensure that direction is local + return centerTargetPos.subtract(centerHeadPos).normalize(); + } + + //TODO memory optimize this + @WrapMethod(method = "basicRaycast") + private BlockPos test23929(Vec3 from, Vec3 direction, final int range, final float searchOffset, final Operation original) { + final BlockPos localCast = original.call(from, direction, range, searchOffset); + double minDistance = Double.MAX_VALUE; + BlockPos gatheredPos = null; + if (localCast != null) { + gatheredPos = localCast; + minDistance = localCast.distToCenterSqr(from); + } + + final SubLevel parentSublevel = Sable.HELPER.getContaining(this.getLevel(), from); + if (parentSublevel != null) { + direction = parentSublevel.logicalPose().transformNormal(direction); + from = parentSublevel.logicalPose().transformPosition(from); + } + + final BlockPos globalCast = original.call(from, direction, range, searchOffset); + if (globalCast != null) { + final double globalDist = globalCast.distToCenterSqr(from); + if (gatheredPos == null || globalDist < minDistance) { + minDistance = globalDist; + gatheredPos = globalCast; + } + } + + final Vec3 target = from.add(direction.scale(range)); + //TODO make these static members + final BoundingBox3d searchBounds = new BoundingBox3d(from.x, from.y, from.z, target.x, target.y, target.z); + final Vector3d tempOrigin = new Vector3d(); + final Vector3d tempDir = new Vector3d(); + // + + for (final SubLevel subLevel : Sable.HELPER.getAllIntersecting(this.getLevel(), searchBounds)) { + if (subLevel == parentSublevel) { + continue; + } + + subLevel.logicalPose().transformPositionInverse(tempOrigin.set(from.x, from.y, from.z)); + subLevel.logicalPose().transformNormalInverse(tempDir.set(direction.x, direction.y, direction.z)); + + final BlockPos sublevelCall = original.call(new Vec3(tempOrigin.x, tempOrigin.y, tempOrigin.z), new Vec3(tempDir.x, tempDir.y, tempDir.z), range, searchOffset / 2f); + if (sublevelCall != null) { + final double sublevelDist = sublevelCall.distToCenterSqr(tempOrigin.x, tempOrigin.y, tempOrigin.z); + if (gatheredPos == null || sublevelDist < minDistance) { + minDistance = sublevelDist; + gatheredPos = sublevelCall; + } + } + } + + return gatheredPos; + } + + +} diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/rendering/LaserArmModelMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/rendering/LaserArmModelMixin.java new file mode 100644 index 00000000..5dbe4282 --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/rendering/LaserArmModelMixin.java @@ -0,0 +1,56 @@ +package dev.ryanhcode.sable.mixin.compatibility.oritech.rendering; + +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import dev.ryanhcode.sable.Sable; +import dev.ryanhcode.sable.sublevel.ClientSubLevel; +import dev.ryanhcode.sable.sublevel.SubLevel; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import rearth.oritech.block.entity.interaction.LaserArmBlockEntity; +import rearth.oritech.client.renderers.LaserArmModel; +import software.bernie.geckolib.animatable.GeoAnimatable; +import software.bernie.geckolib.animation.AnimationState; + +@Mixin(LaserArmModel.class) +public class LaserArmModelMixin { + + @Inject(method = "setCustomAnimations(Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;JLsoftware/bernie/geckolib/animation/AnimationState;)V", at = @At("HEAD")) + public void test(final T laserEntity, final long instanceId, final AnimationState animationState, final CallbackInfo ci, @Share("parent_sublevel") final LocalRef sublevel) { + sublevel.set(Sable.HELPER.getContainingClient(laserEntity.getBlockPos())); + } + + @Redirect(method = "setCustomAnimations(Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;JLsoftware/bernie/geckolib/animation/AnimationState;)V", at = @At(value = "INVOKE", target = "Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;getVisualTarget()Lnet/minecraft/world/phys/Vec3;")) + public Vec3 sable$projectTargetPos(final LaserArmBlockEntity instance, @Share("parent_sublevel") final LocalRef parentSublevel) { + return sable$transformPos(instance.getVisualTarget(), parentSublevel.get()); + } + + @Redirect(method = "setCustomAnimations(Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;JLsoftware/bernie/geckolib/animation/AnimationState;)V", at = @At(value = "FIELD", target = "Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;laserHead:Lnet/minecraft/world/phys/Vec3;", opcode = Opcodes.GETFIELD)) + public Vec3 sable$projectHeadPos(final LaserArmBlockEntity instance, @Share("parent_sublevel") final LocalRef parentSublevel) { + return sable$transformPos(instance.laserHead, parentSublevel.get()); + } + + @Unique + private static Vec3 sable$transformPos(Vec3 pos, @Nullable final ClientSubLevel parentSublevel) { + final ClientSubLevel clientSublevel = Sable.HELPER.getContainingClient(pos); + + if (clientSublevel != null) { + pos = clientSublevel.renderPose().transformPosition(pos); + } + + if (parentSublevel != null) { + pos = parentSublevel.renderPose().transformPositionInverse(pos); + } + + return pos; + } + +} diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/rendering/LaserArmRendererMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/rendering/LaserArmRendererMixin.java new file mode 100644 index 00000000..ca04c84d --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/oritech/rendering/LaserArmRendererMixin.java @@ -0,0 +1,60 @@ +package dev.ryanhcode.sable.mixin.compatibility.oritech.rendering; + +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import dev.ryanhcode.sable.Sable; +import dev.ryanhcode.sable.sublevel.ClientSubLevel; +import dev.ryanhcode.sable.sublevel.SubLevel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import rearth.oritech.block.entity.interaction.LaserArmBlockEntity; +import rearth.oritech.client.renderers.LaserArmRenderer; +import software.bernie.geckolib.animatable.GeoAnimatable; +import software.bernie.geckolib.cache.object.BakedGeoModel; + +@Mixin(LaserArmRenderer.class) +public class LaserArmRendererMixin { + + @Inject(method = "postRender(Lcom/mojang/blaze3d/vertex/PoseStack;Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;Lsoftware/bernie/geckolib/cache/object/BakedGeoModel;Lnet/minecraft/client/renderer/MultiBufferSource;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZFIII)V", at = @At("HEAD")) + public void test(final PoseStack matrices, final T laserEntity, final BakedGeoModel model, final MultiBufferSource bufferSource, @Nullable final VertexConsumer buffer, final boolean isReRender, final float partialTick, final int packedLight, final int packedOverlay, final int colour, final CallbackInfo ci, @Share("parent_sublevel") final LocalRef sublevel) { + sublevel.set(Sable.HELPER.getContainingClient(laserEntity.getBlockPos())); + } + + @Redirect(method = "postRender(Lcom/mojang/blaze3d/vertex/PoseStack;Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;Lsoftware/bernie/geckolib/cache/object/BakedGeoModel;Lnet/minecraft/client/renderer/MultiBufferSource;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZFIII)V", at = @At(value = "INVOKE", target = "Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;getVisualTarget()Lnet/minecraft/world/phys/Vec3;")) + public Vec3 sable$projectTargetPos(final LaserArmBlockEntity instance, @Share("parent_sublevel") final LocalRef parentSublevel) { + return sable$transformPos(instance.getVisualTarget(), parentSublevel.get()); + } + + @Redirect(method = "postRender(Lcom/mojang/blaze3d/vertex/PoseStack;Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;Lsoftware/bernie/geckolib/cache/object/BakedGeoModel;Lnet/minecraft/client/renderer/MultiBufferSource;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZFIII)V", at = @At(value = "FIELD", target = "Lrearth/oritech/block/entity/interaction/LaserArmBlockEntity;laserHead:Lnet/minecraft/world/phys/Vec3;", opcode = Opcodes.GETFIELD)) + public Vec3 sable$projectHeadPos(final LaserArmBlockEntity instance, @Share("parent_sublevel") final LocalRef parentSublevel) { + return sable$transformPos(instance.laserHead, parentSublevel.get()); + } + + //transform the target position into the parent sublevel if applicable, or transform parent position into target sublevel + @Unique + private static Vec3 sable$transformPos(Vec3 pos, @Nullable final ClientSubLevel parentSublevel) { + final ClientSubLevel clientSublevel = Sable.HELPER.getContainingClient(pos); + + if (clientSublevel != null) { + pos = clientSublevel.renderPose().transformPosition(pos); + } + + if (parentSublevel != null) { + pos = parentSublevel.renderPose().transformPositionInverse(pos); + } + + return pos; + } + +} diff --git a/common/src/main/resources/sable.mixins.json b/common/src/main/resources/sable.mixins.json index b37909c7..09b7ac03 100644 --- a/common/src/main/resources/sable.mixins.json +++ b/common/src/main/resources/sable.mixins.json @@ -17,6 +17,8 @@ "clip_overwrite.ClientLevelMixin", "clip_overwrite.GameRendererMixin", "compatibility.iris.ExtendedShaderMixin", + "compatibility.oritech.rendering.LaserArmRendererMixin", + "compatibility.oritech.rendering.LaserArmModelMixin", "config.GameRendererAccessor", "debug_render.DebugRendererMixin", "debug_render.DebugScreenOverlayMixin", @@ -101,6 +103,7 @@ "compatibility.jade.BlockAccessorImplMixin", "compatibility.jade.RayTracingMixin", "compatibility.jadeaddons.CreatePluginMixin", + "compatibility.oritech.LaserArmBlockEntityMixin", "compatibility.vista.LODMixin", "compatibility.vista.ViewFinderAccessMixin", "compatibility.vista.ViewFinderControllerMixin", diff --git a/gradle.properties b/gradle.properties index 3758b6cc..6e18f618 100644 --- a/gradle.properties +++ b/gradle.properties @@ -56,6 +56,11 @@ distant_horizons_version=2.2.1-a-1.21.1 nml_version=1.4.3 sodiumextras_version=1.0.8 +#oritech compat +oritech_version=1.2.3 +geckolib_version = 4.6.6 +architectury_api_version = 13.0.8 + loom.ignoreDependencyLoomVersionValidation=true org.gradle.jvmargs=-Xmx4G diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 8d554bf8..7584e94c 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -94,6 +94,11 @@ dependencies { compileOnly("maven.modrinth:iris:$iris_version") { transitive = false } compileOnly("maven.modrinth:sodium-extras:neoforge-${minecraft_version}-$sodiumextras_version") { transitive = false } + implementation "rearth.oritech:oritech-neoforge-${minecraft_version}:${oritech_version}" + implementation "software.bernie.geckolib:geckolib-neoforge-$minecraft_version:$geckolib_version" + implementation "earth.terrarium.athena:athena-neoforge-1.21:4.0.0" + implementation "dev.architectury:architectury-neoforge:$architectury_api_version" + jarJar(api("foundry.veil:veil-neoforge-${project.minecraft_version}:${project.veil_version}") { exclude group: "maven.modrinth" exclude group: "me.fallenbreath"