diff --git a/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java b/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java index 9a4884fc..0d277a3a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java @@ -7,6 +7,9 @@ import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -63,6 +66,27 @@ public interface HexAPI { return Component.translatable(getRawHookI18nKey(name)).withStyle(ChatFormatting.LIGHT_PURPLE); } + /** + * Register an entity with the given ID to have its velocity as perceived by OpEntityVelocity be different + * than it's "normal" velocity + */ + // Should be OK to use the type directly as the key as they're singleton identity objects + default void registerSpecialVelocityGetter(EntityType key, EntityVelocityGetter getter) { + } + + /** + * If the entity has had a special getter registered with {@link HexAPI#registerSpecialVelocityGetter} then + * return that, otherwise return its normal delta movement + */ + default Vec3 getEntityVelocitySpecial(Entity entity) { + return entity.getDeltaMovement(); + } + + @FunctionalInterface + interface EntityVelocityGetter { + Vec3 getVelocity(T entity); + } + static HexAPI instance() { return INSTANCE.get(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/OpEntityVelocity.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/OpEntityVelocity.kt index 5430e154..c5152d4e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/OpEntityVelocity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/OpEntityVelocity.kt @@ -1,12 +1,11 @@ package at.petrak.hexcasting.common.casting.operators -import at.petrak.hexcasting.api.casting.castables.ConstMediaAction +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.asActionResult +import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.getEntity import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.common.misc.PlayerPositionRecorder -import net.minecraft.server.level.ServerPlayer object OpEntityVelocity : ConstMediaAction { override val argc = 1 @@ -15,11 +14,7 @@ object OpEntityVelocity : ConstMediaAction { val e = args.getEntity(0, argc) ctx.assertEntityInRange(e) - // Player velocity is jank. Really jank. This is the best we can do. - if (e is ServerPlayer) { - return PlayerPositionRecorder.getMotion(e).asActionResult - } - - return e.deltaMovement.asActionResult + val vel = HexAPI.instance().getEntityVelocitySpecial(e) + return vel.asActionResult } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java b/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java index 4e60c933..35a627d9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java @@ -1,6 +1,30 @@ package at.petrak.hexcasting.common.impl; import at.petrak.hexcasting.api.HexAPI; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; public class HexAPIImpl implements HexAPI { + private static final ConcurrentMap, EntityVelocityGetter> SPECIAL_VELOCITIES + = new ConcurrentHashMap<>(); + + public void registerSpecialVelocityGetter(EntityType key, + EntityVelocityGetter getter) { + SPECIAL_VELOCITIES.put(key, getter); + } + + @Override + public Vec3 getEntityVelocitySpecial(Entity entity) { + EntityType type = entity.getType(); + if (SPECIAL_VELOCITIES.containsKey(type)) { + var velGetter = SPECIAL_VELOCITIES.get(type); + var erasedGetter = (EntityVelocityGetter) velGetter; + return erasedGetter.getVelocity(entity); + } + return entity.getDeltaMovement(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/VelocityFudging.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/VelocityFudging.java new file mode 100644 index 00000000..5a3fd722 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/VelocityFudging.java @@ -0,0 +1,28 @@ +package at.petrak.hexcasting.common.misc; + +import at.petrak.hexcasting.api.HexAPI; +import at.petrak.hexcasting.mixin.accessor.AccessorAbstractArrow; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; + +public class VelocityFudging { + public static void register() { + HexAPI.instance().registerSpecialVelocityGetter(EntityType.PLAYER, player -> { + if (player instanceof ServerPlayer splayer) { + return PlayerPositionRecorder.getMotion(splayer); + } else { + // bruh + throw new IllegalStateException("Call this only on the server side, silly"); + } + }); + + HexAPI.instance().registerSpecialVelocityGetter(EntityType.ARROW, arrow -> { + if (((AccessorAbstractArrow) arrow).hex$isInGround()) { + return Vec3.ZERO; + } else { + return arrow.getDeltaMovement(); + } + }); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java new file mode 100644 index 00000000..b956033d --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java @@ -0,0 +1,11 @@ +package at.petrak.hexcasting.mixin.accessor; + +import net.minecraft.world.entity.projectile.AbstractArrow; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AbstractArrow.class) +public interface AccessorAbstractArrow { + @Accessor("inGround") + boolean hex$isInGround(); +} diff --git a/Common/src/main/resources/hexplat.mixins.json b/Common/src/main/resources/hexplat.mixins.json index c10df093..24fa76d1 100644 --- a/Common/src/main/resources/hexplat.mixins.json +++ b/Common/src/main/resources/hexplat.mixins.json @@ -10,6 +10,7 @@ "MixinRaider", "MixinVillager", "MixinWitch", + "accessor.AccessorAbstractArrow", "accessor.AccessorEntity", "accessor.AccessorLivingEntity", "accessor.AccessorLootTable", diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt index 0fbb07d9..4c93ca41 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt @@ -22,6 +22,7 @@ import at.petrak.hexcasting.common.lib.hex.HexSpecialHandlers import at.petrak.hexcasting.common.misc.AkashicTreeGrower import at.petrak.hexcasting.common.misc.BrainsweepingEvents import at.petrak.hexcasting.common.misc.PlayerPositionRecorder +import at.petrak.hexcasting.common.misc.VelocityFudging import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry import at.petrak.hexcasting.fabric.event.VillagerConversionCallback import at.petrak.hexcasting.fabric.interop.gravity.GravityApiInterop @@ -71,6 +72,7 @@ object FabricHexInitializer : ModInitializer { FabricImpetusStorage.registerStorage() HexInterop.init() + VelocityFudging.register() } fun initListeners() { diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java index 2a6bf4e8..643f63c8 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java @@ -19,6 +19,7 @@ import at.petrak.hexcasting.common.lib.hex.HexSpecialHandlers; import at.petrak.hexcasting.common.misc.AkashicTreeGrower; import at.petrak.hexcasting.common.misc.BrainsweepingEvents; import at.petrak.hexcasting.common.misc.PlayerPositionRecorder; +import at.petrak.hexcasting.common.misc.VelocityFudging; import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry; import at.petrak.hexcasting.forge.cap.CapSyncers; import at.petrak.hexcasting.forge.cap.ForgeCapabilityHandler; @@ -114,6 +115,8 @@ public class ForgeHexInitializer { ForgeHexLootMods.REGISTRY.register(getModEventBus()); HexAdvancementTriggers.registerTriggers(); + + VelocityFudging.register(); } // https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java