From 02f817c3df1a84a948a61dd48eaa39b6e601cdf9 Mon Sep 17 00:00:00 2001 From: Pyrofab Date: Mon, 17 Jun 2024 01:44:10 +0200 Subject: [PATCH] Refactor riding and jumping APIs into a separate module --- build.gradle | 1 + .../requiem/api/v1/internal/ApiInternals.java | 6 -- requiem-core/build.gradle | 1 + requiem-core/vaquero/build.gradle | 18 ++++ .../vaquero/api}/ExternalJumpingMount.java | 12 ++- .../ladysnake/vaquero/api/MobRidingType.java | 57 ++++++++++++ .../api/events/JumpingMountEvents.java | 65 ++++++++++++++ .../api/events}/MobTravelRidingCallback.java | 2 +- .../ladysnake/vaquero/api/package-info.java | 12 +++ .../org/ladysnake/vaquero/impl/Vaquero.java | 41 +++++++++ .../vaquero/impl/VaqueroEntityTypeTags.java | 31 +++++++ .../impl/jump/DummyHorseJumpingMount.java | 32 +++---- .../vaquero/impl}/jump/DummyJumpingMount.java | 71 ++++++--------- .../impl/jump/DummyNoDragJumpingMount.java | 60 +++++++++++++ .../impl/mixin/PossessionRidingHelper.java | 48 ++++++++++ .../mixin/client/ClientPlayerEntityMixin.java | 58 ++++++++++++ .../impl/mixin/client/package-info.java | 12 +++ .../impl/mixin/common/EntityAccessor.java | 28 ++++++ .../impl/mixin/common/EntityMixin.java | 49 +++++++++++ .../mixin/common/LivingEntityAccessor.java | 13 +-- .../impl/mixin/common/LivingEntityMixin.java | 83 ++++++++++++++++++ .../impl/mixin/common/MobEntityMixin.java | 80 +++++++++++++++++ .../common/ServerPlayNetworkHandlerMixin.java | 64 ++++++++++++++ .../impl/mixin/common/package-info.java | 12 +++ .../vaquero/impl/mixin/package-info.java | 12 +++ .../main/resources/mixins.vaquero.client.json | 9 ++ .../main/resources/mixins.vaquero.common.json | 17 ++++ .../vaquero/src/main/resources/quilt.mod.json | 42 +++++++++ .../vaquero/src/main/resources/skull_logo.png | Bin 0 -> 541 bytes settings.gradle | 1 + .../requiem/common/ApiInitializer.java | 13 --- .../requiem/common/RequiemComponents.java | 16 ++-- .../requiem/common/VanillaRequiemPlugin.java | 9 +- .../common/possession/MobRidingType.java | 72 --------------- .../jump/DummyHorseJumpingMount.java | 49 ----------- .../jump/DummyNoDragJumpingMount.java | 74 ---------------- .../remnant/BasePossessionHandlers.java | 3 - .../common/tag/RequiemEntityTypeTags.java | 2 - .../compat/RequiemCompatibilityManager.java | 3 +- .../riding/ClientPlayerEntityMixin.java | 80 ----------------- .../possession/gameplay/CatEntityMixin.java | 7 -- .../gameplay/EntityMixin.java} | 15 ++-- .../possession/gameplay/FoxEntityMixin.java | 6 -- .../gameplay/LivingEntityMixin.java | 40 +-------- .../possession/gameplay/MobEntityMixin.java | 71 --------------- .../ServerPlayNetworkHandlerMixin.java | 76 ---------------- src/main/resources/mixins.requiem.client.json | 1 - src/main/resources/mixins.requiem.common.json | 3 +- 48 files changed, 892 insertions(+), 585 deletions(-) create mode 100644 requiem-core/vaquero/build.gradle rename {requiem-api/src/main/java/ladysnake/requiem/api/v1/entity => requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api}/ExternalJumpingMount.java (87%) create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/MobRidingType.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/JumpingMountEvents.java rename {requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft => requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events}/MobTravelRidingCallback.java (96%) create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/package-info.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/Vaquero.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/VaqueroEntityTypeTags.java rename requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/JumpingMountEvents.java => requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyHorseJumpingMount.java (51%) rename {src/main/java/ladysnake/requiem/common/possession => requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl}/jump/DummyJumpingMount.java (56%) create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyNoDragJumpingMount.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/PossessionRidingHelper.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/ClientPlayerEntityMixin.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/package-info.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityAccessor.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityMixin.java rename requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ExternalJumpingMountFactory.java => requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityAccessor.java (67%) create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityMixin.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/MobEntityMixin.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/ServerPlayNetworkHandlerMixin.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/package-info.java create mode 100644 requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/package-info.java create mode 100644 requiem-core/vaquero/src/main/resources/mixins.vaquero.client.json create mode 100644 requiem-core/vaquero/src/main/resources/mixins.vaquero.common.json create mode 100644 requiem-core/vaquero/src/main/resources/quilt.mod.json create mode 100644 requiem-core/vaquero/src/main/resources/skull_logo.png delete mode 100644 src/main/java/ladysnake/requiem/common/possession/MobRidingType.java delete mode 100644 src/main/java/ladysnake/requiem/common/possession/jump/DummyHorseJumpingMount.java delete mode 100644 src/main/java/ladysnake/requiem/common/possession/jump/DummyNoDragJumpingMount.java delete mode 100644 src/main/java/ladysnake/requiem/mixin/client/possession/riding/ClientPlayerEntityMixin.java rename src/main/java/ladysnake/requiem/mixin/common/{access/EntityAccessor.java => possession/gameplay/EntityMixin.java} (85%) delete mode 100644 src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerPlayNetworkHandlerMixin.java diff --git a/build.gradle b/build.gradle index e4e5fa747..7d3542fea 100644 --- a/build.gradle +++ b/build.gradle @@ -152,6 +152,7 @@ dependencies { // Required dependencies api include(project(path: ":requiem-api", configuration: "namedElements")) { transitive = false } api include(project(path: ":requiem-core", configuration: "namedElements")) { transitive = false } + api include(project(path: ":requiem-core:vaquero", configuration: "namedElements")) modImplementation(libs.bundles.requiredLibraries) { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" diff --git a/requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ApiInternals.java b/requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ApiInternals.java index f4738ee04..f8481c9f1 100644 --- a/requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ApiInternals.java +++ b/requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ApiInternals.java @@ -78,8 +78,6 @@ public final class ApiInternals { private static SoulbindingRegistry soulbindingRegistry; @AccessedThroughReflection private static Function<@Nullable World, MovementRegistry> movementRegistryGetter; - @AccessedThroughReflection - private static ExternalJumpingMountFactory externalJumpingMountFactory; @SuppressWarnings("unchecked") public static MobAbilityConfig.Builder mobAbilityConfig$builderImpl() { @@ -132,10 +130,6 @@ public static MovementRegistry getMovementRegistry(@Nullable World world) { return movementRegistryGetter.apply(world); } - public static ExternalJumpingMountFactory getExternalJumpingMountFactory() { - return externalJumpingMountFactory; - } - public static InventoryLimiter getInventoryLimiter() { return inventoryLimiter; } diff --git a/requiem-core/build.gradle b/requiem-core/build.gradle index 948f0a8ae..b6004aaa2 100644 --- a/requiem-core/build.gradle +++ b/requiem-core/build.gradle @@ -3,6 +3,7 @@ group = rootProject.group dependencies { api project(path: ":requiem-api", configuration: "namedElements") + api(project(path: ":requiem-core:vaquero", configuration: "namedElements")) modImplementation(libs.playerAbilityLib) { exclude group: "net.fabricmc" } diff --git a/requiem-core/vaquero/build.gradle b/requiem-core/vaquero/build.gradle new file mode 100644 index 000000000..f27a447ea --- /dev/null +++ b/requiem-core/vaquero/build.gradle @@ -0,0 +1,18 @@ +archivesBaseName = "vaquero" +group = rootProject.group + ".requiem" + +dependencies { + modImplementation(libs.cca.base) { + exclude group: "net.fabricmc" + } + modImplementation(libs.cca.entity) { + exclude group: "net.fabricmc" + } +} + +chenille { + license = 'LGPL' + configurePublishing { + withLadysnakeMaven() + } +} diff --git a/requiem-api/src/main/java/ladysnake/requiem/api/v1/entity/ExternalJumpingMount.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/ExternalJumpingMount.java similarity index 87% rename from requiem-api/src/main/java/ladysnake/requiem/api/v1/entity/ExternalJumpingMount.java rename to requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/ExternalJumpingMount.java index 61ee2fbf9..f4f536879 100644 --- a/requiem-api/src/main/java/ladysnake/requiem/api/v1/entity/ExternalJumpingMount.java +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/ExternalJumpingMount.java @@ -15,20 +15,24 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program; If not, see . */ -package ladysnake.requiem.api.v1.entity; +package org.ladysnake.vaquero.api; import dev.onyxstudios.cca.api.v3.component.Component; import dev.onyxstudios.cca.api.v3.component.ComponentFactory; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import ladysnake.requiem.api.v1.internal.ApiInternals; import net.minecraft.entity.JumpingMount; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; import org.apiguardian.api.API; +import org.jetbrains.annotations.Nullable; +import org.ladysnake.vaquero.impl.jump.DummyJumpingMount; + +import java.util.function.Function; /** * A fake {@link JumpingMount} that is not implemented by a rideable entity. @@ -39,8 +43,8 @@ public interface ExternalJumpingMount extends JumpingMount, Component { ComponentKey KEY = ComponentRegistry.getOrCreate(new Identifier("requiem", "charged_jump"), ExternalJumpingMount.class); - static ComponentFactory simple(float baseJumpStrength, SoundEvent stepSound) { - return ApiInternals.getExternalJumpingMountFactory().simple(baseJumpStrength, stepSound); + static ComponentFactory simple(float baseJumpStrength, SoundEvent stepSound, Function getPlayer) { + return e -> new DummyJumpingMount(e, baseJumpStrength, stepSound, getPlayer); } /** diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/MobRidingType.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/MobRidingType.java new file mode 100644 index 000000000..bbe8b87c9 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/MobRidingType.java @@ -0,0 +1,57 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.api; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.RavagerEntity; +import net.minecraft.entity.mob.SkeletonEntity; +import net.minecraft.entity.mob.SpiderEntity; +import net.minecraft.entity.passive.ChickenEntity; +import net.minecraft.entity.passive.StriderEntity; +import net.minecraft.registry.tag.EntityTypeTags; +import org.apiguardian.api.API; +import org.ladysnake.vaquero.impl.VaqueroEntityTypeTags; + +@API(status = API.Status.EXPERIMENTAL, since = "2.0.0") +public enum MobRidingType { + DEFAULT, MOUNT, RIDE; + + public boolean canMount() { + return this != DEFAULT; + } + + public boolean canSteer() { + return this == RIDE; + } + + public static MobRidingType get(Entity entity, LivingEntity possessed) { + if (entity instanceof SpiderEntity) { + return possessed instanceof SkeletonEntity ? MOUNT : DEFAULT; + } else if (entity instanceof RavagerEntity) { + return possessed.getType().isIn(EntityTypeTags.RAIDERS) ? RIDE : DEFAULT; + } else if (entity instanceof ChickenEntity) { + return possessed.getType().isIn(VaqueroEntityTypeTags.ZOMBIES) && possessed.isBaby() ? RIDE : DEFAULT; + } else if (entity instanceof StriderEntity) { + return possessed.getType() == EntityType.ZOMBIFIED_PIGLIN || possessed.getType().isIn(VaqueroEntityTypeTags.PIGLINS) ? RIDE : DEFAULT; + } + + return DEFAULT; + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/JumpingMountEvents.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/JumpingMountEvents.java new file mode 100644 index 000000000..9d2d339ef --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/JumpingMountEvents.java @@ -0,0 +1,65 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.api.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.entity.JumpingMount; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import org.jetbrains.annotations.Nullable; + +public final class JumpingMountEvents { + /** + * Finds the {@link JumpingMount} associated with an entity + */ + public static final Event FIND_ENTITY_JUMP = EventFactory.createArrayBacked(FindEntityJumpingMountCallback.class, callbacks -> entity -> { + for (FindEntityJumpingMountCallback callback : callbacks) { + JumpingMount mount = callback.findJumpingMount(entity); + if (mount != null) { + return mount; + } + } + return null; + }); + + /** + * Finds the {@link JumpingMount} controlled by the given player + */ + public static final Event FIND_PLAYER_JUMP = EventFactory.createArrayBacked(FindPlayerJumpingMountCallback.class, callbacks -> entity -> { + for (FindPlayerJumpingMountCallback callback : callbacks) { + JumpingMount mount = callback.findJumpingMount(entity); + if (mount != null) { + return mount; + } + } + return null; + }); + + @FunctionalInterface + public interface FindEntityJumpingMountCallback { + @Nullable + JumpingMount findJumpingMount(LivingEntity entity); + } + + @FunctionalInterface + public interface FindPlayerJumpingMountCallback { + @Nullable + JumpingMount findJumpingMount(PlayerEntity entity); + } +} diff --git a/requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/MobTravelRidingCallback.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/MobTravelRidingCallback.java similarity index 96% rename from requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/MobTravelRidingCallback.java rename to requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/MobTravelRidingCallback.java index ceb6650e5..a9d5950cb 100644 --- a/requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/MobTravelRidingCallback.java +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/events/MobTravelRidingCallback.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program; If not, see . */ -package ladysnake.requiem.api.v1.event.minecraft; +package org.ladysnake.vaquero.api.events; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/package-info.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/package-info.java new file mode 100644 index 000000000..3b4bba2fd --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/api/package-info.java @@ -0,0 +1,12 @@ +/** + * API classes for Vaquero + */ +@FieldsAreNonnullByDefault +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package org.ladysnake.vaquero.api; + +import net.minecraft.util.annotation.FieldsAreNonnullByDefault; +import net.minecraft.util.annotation.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/Vaquero.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/Vaquero.java new file mode 100644 index 000000000..6713cc643 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/Vaquero.java @@ -0,0 +1,41 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.Identifier; +import org.ladysnake.vaquero.api.ExternalJumpingMount; +import org.ladysnake.vaquero.api.events.JumpingMountEvents; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; + +public final class Vaquero implements ModInitializer { + public static Identifier id(String path) { + return new Identifier("vaquero", path); + } + + @Override + public void onInitialize(ModContainer mod) { + JumpingMountEvents.FIND_ENTITY_JUMP.register(ExternalJumpingMount.KEY::getNullable); + JumpingMountEvents.FIND_PLAYER_JUMP.register(player -> { + Entity controlledVehicle = player.getControlledVehicle(); + return controlledVehicle instanceof LivingEntity living ? JumpingMountEvents.FIND_ENTITY_JUMP.invoker().findJumpingMount(living) : null; + }); + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/VaqueroEntityTypeTags.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/VaqueroEntityTypeTags.java new file mode 100644 index 000000000..efe419087 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/VaqueroEntityTypeTags.java @@ -0,0 +1,31 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl; + +import net.minecraft.entity.EntityType; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; + +public final class VaqueroEntityTypeTags { + public static final TagKey> ZOMBIES = register("zombies"); + public static final TagKey> PIGLINS = register("piglins"); + + public static TagKey> register(String name) { + return TagKey.of(RegistryKeys.ENTITY_TYPE, Vaquero.id(name)); + } +} diff --git a/requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/JumpingMountEvents.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyHorseJumpingMount.java similarity index 51% rename from requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/JumpingMountEvents.java rename to requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyHorseJumpingMount.java index c49a2eb63..965988578 100644 --- a/requiem-api/src/main/java/ladysnake/requiem/api/v1/event/minecraft/JumpingMountEvents.java +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyHorseJumpingMount.java @@ -15,31 +15,23 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program; If not, see . */ -package ladysnake.requiem.api.v1.event.minecraft; +package org.ladysnake.vaquero.impl.jump; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.entity.JumpingMount; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.passive.HorseBaseEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.sound.SoundEvent; import org.jetbrains.annotations.Nullable; -public final class JumpingMountEvents { - /** - * - */ - public static final Event MOUNT_CHECK = EventFactory.createArrayBacked(MountCheckCallback.class, callbacks -> entity -> { - for (MountCheckCallback callback : callbacks) { - JumpingMount mount = callback.getJumpingMount(entity); - if (mount != null) { - return mount; - } - } - return null; - }); +import java.util.function.Function; - @FunctionalInterface - public interface MountCheckCallback { - @Nullable JumpingMount getJumpingMount(LivingEntity entity); +public class DummyHorseJumpingMount extends DummyJumpingMount { + public DummyHorseJumpingMount(HorseBaseEntity mob, SoundEvent stepSound, Function getPlayer) { + super(mob, -1, stepSound, getPlayer); } + @Override + protected double getBaseJumpingStrength() { + return ((HorseBaseEntity) this.mob).getJumpStrength(); + } } diff --git a/src/main/java/ladysnake/requiem/common/possession/jump/DummyJumpingMount.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyJumpingMount.java similarity index 56% rename from src/main/java/ladysnake/requiem/common/possession/jump/DummyJumpingMount.java rename to requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyJumpingMount.java index 4805a0571..6f95329f2 100644 --- a/src/main/java/ladysnake/requiem/common/possession/jump/DummyJumpingMount.java +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyJumpingMount.java @@ -2,43 +2,23 @@ * Requiem * Copyright (C) 2017-2024 Ladysnake * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Linking this mod statically or dynamically with other - * modules is making a combined work based on this mod. - * Thus, the terms and conditions of the GNU General Public License cover the whole combination. - * - * In addition, as a special exception, the copyright holders of - * this mod give you permission to combine this mod - * with free software programs or libraries that are released under the GNU LGPL - * and with code included in the standard release of Minecraft under All Rights Reserved (or - * modified versions of such code, with unchanged license). - * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the other code concerned. - * - * Note that people who make modified versions of this mod are not obligated to grant - * this special exception for their modified versions; it is their choice whether to do so. - * The GNU General Public License gives permission to release a modified version without this exception; - * this exception also makes it possible to release a modified version which carries forward this exception. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . */ -package ladysnake.requiem.common.possession.jump; +package org.ladysnake.vaquero.impl.jump; import com.google.common.base.Preconditions; import dev.onyxstudios.cca.api.v3.component.TransientComponent; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; -import ladysnake.requiem.api.v1.possession.Possessable; -import ladysnake.requiem.mixin.common.access.EntityAccessor; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.EntityPose; import net.minecraft.entity.LivingEntity; @@ -49,6 +29,11 @@ import net.minecraft.sound.SoundEvent; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.Nullable; +import org.ladysnake.vaquero.api.ExternalJumpingMount; +import org.ladysnake.vaquero.impl.mixin.common.EntityAccessor; + +import java.util.function.Function; /** * A fake JumpingMount that allows players possessing a mob to long jump by themselves @@ -60,11 +45,13 @@ public class DummyJumpingMount implements ExternalJumpingMount, TransientCompone /**@see HorseBaseEntity#isInAir()*/ private boolean inAir; private final double baseJumpStrength; + private final Function getPlayer; - public DummyJumpingMount(LivingEntity mob, double baseJumpStrength, SoundEvent stepSound) { + public DummyJumpingMount(LivingEntity mob, double baseJumpStrength, SoundEvent stepSound, Function getPlayer) { this.mob = mob; this.baseJumpStrength = baseJumpStrength; this.stepSound = stepSound; + this.getPlayer = getPlayer; } @Override @@ -72,7 +59,7 @@ public void setJumpStrength(int strength) { if (strength < 0) { strength = 0; } else { - PlayerEntity possessor = ((Possessable) this.mob).getPossessor(); + PlayerEntity possessor = this.getPlayer.apply(this.mob); if (possessor != null) { possessor.setJumping(true); } @@ -103,26 +90,26 @@ public void stopJumping() { @Override public void attemptJump() { - PlayerEntity possessor = ((Possessable) this.mob).getPossessor(); + PlayerEntity player = getPlayer.apply(this.mob); - if (possessor != null && possessor.isOnGround()) { + if (player != null && player.isOnGround()) { if (!this.inAir && this.jumpStrength > 0.0F) { double naturalStrength = getBaseJumpingStrength(); double baseJumpVelocity = naturalStrength * this.jumpStrength * ((EntityAccessor) this.mob).requiem$invokeGetJumpVelocityMultiplier(); double jumpVelocity = baseJumpVelocity + this.mob.getJumpBoostVelocityModifier(); - Vec3d baseVelocity = possessor.getVelocity(); - possessor.setVelocity(baseVelocity.x, jumpVelocity, baseVelocity.z); + Vec3d baseVelocity = player.getVelocity(); + player.setVelocity(baseVelocity.x, jumpVelocity, baseVelocity.z); this.inAir = true; - possessor.velocityDirty = true; - if (possessor.forwardSpeed > 0.0F) { - float vx = MathHelper.sin(possessor.getYaw() * (float) (Math.PI / 180.0)); - float vz = MathHelper.cos(possessor.getYaw() * (float) (Math.PI / 180.0)); - possessor.setVelocity(possessor.getVelocity().add(-0.4F * vx * this.jumpStrength, 0.0, 0.4F * vz * this.jumpStrength)); + player.velocityDirty = true; + if (player.forwardSpeed > 0.0F) { + float vx = MathHelper.sin(player.getYaw() * (float) (Math.PI / 180.0)); + float vz = MathHelper.cos(player.getYaw() * (float) (Math.PI / 180.0)); + player.setVelocity(player.getVelocity().add(-0.4F * vx * this.jumpStrength, 0.0, 0.4F * vz * this.jumpStrength)); } - this.beginClientJump(possessor); + this.beginClientJump(player); } else if (this.inAir) { - this.finishClientJump(possessor); + this.finishClientJump(player); } } } diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyNoDragJumpingMount.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyNoDragJumpingMount.java new file mode 100644 index 000000000..eea199297 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/jump/DummyNoDragJumpingMount.java @@ -0,0 +1,60 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.jump; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.sound.SoundEvent; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +/** + * Currently unused because setting noDrag means you have to revert it when dissociating and lazy + *
+ * But it allows doing epic jumps as a goat + */ +public class DummyNoDragJumpingMount extends DummyJumpingMount { + public DummyNoDragJumpingMount(LivingEntity mob, SoundEvent stepSound, Function getPlayer) { + super(mob, 1, stepSound, getPlayer); + } + + @Override + protected void beginClientJump(PlayerEntity possessor) { + super.beginClientJump(possessor); + possessor.setNoDrag(true); + } + + @Override + protected void finishClientJump(PlayerEntity possessor) { + super.finishClientJump(possessor); + possessor.setNoDrag(false); + } + + @Override + public void startJumping(int height) { + this.mob.setNoDrag(true); + super.startJumping(height); + } + + @Override + public void stopJumping() { + super.stopJumping(); + this.mob.setNoDrag(false); + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/PossessionRidingHelper.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/PossessionRidingHelper.java new file mode 100644 index 000000000..f5a1cbd9d --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/PossessionRidingHelper.java @@ -0,0 +1,48 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; +import org.ladysnake.vaquero.api.events.MobTravelRidingCallback; + +public final class PossessionRidingHelper { + public static @Nullable LivingEntity getRider(Entity instance, @Nullable LivingEntity vanillaRider) { + if (vanillaRider == null) { + if (instance instanceof MobEntity mob && instance.getFirstPassenger() instanceof LivingEntity livingPassenger) { + if (MobTravelRidingCallback.EVENT.invoker().canBeControlled(mob, livingPassenger)) { + return livingPassenger; + } + } + } + return vanillaRider; + } + + @Contract("_, _, !null -> !null") + public static @Nullable Vec3d getControlledMovement(LivingEntity vehicle, PlayerEntity rider, @Nullable Vec3d input) { + if (vehicle instanceof MobEntity mob && MobTravelRidingCallback.EVENT.invoker().canBeControlled(mob, rider)) { + return new Vec3d(rider.sidewaysSpeed, rider.upwardSpeed, rider.forwardSpeed); + } + return input; + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/ClientPlayerEntityMixin.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/ClientPlayerEntityMixin.java new file mode 100644 index 000000000..5c98edeb8 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/ClientPlayerEntityMixin.java @@ -0,0 +1,58 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin.client; + +import com.mojang.authlib.GameProfile; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.JumpingMount; +import org.ladysnake.vaquero.api.ExternalJumpingMount; +import org.ladysnake.vaquero.api.events.JumpingMountEvents; +import org.ladysnake.vaquero.impl.mixin.common.LivingEntityAccessor; +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.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientPlayerEntity.class) +public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity { + public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) { + super(world, profile); + } + + @Inject(method = "getJumpingMount", at = @At("RETURN"), cancellable = true) + private void hackJumpingMount(CallbackInfoReturnable cir) { + if (cir.getReturnValue() == null && this.getVehicle() == null) { + JumpingMount jumpingMount = JumpingMountEvents.FIND_PLAYER_JUMP.invoker().findJumpingMount(this); + if (jumpingMount != null && jumpingMount.canJump()) { + cir.setReturnValue(jumpingMount); + } + } + } + + @ModifyVariable(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I"), allow = 1) + private JumpingMount swapJumpingMount(JumpingMount mount) { + if (mount instanceof ExternalJumpingMount) { + // prevent normal jumps + ((LivingEntityAccessor) this).setJumpingCooldown(10); + } + return mount; + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/package-info.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/package-info.java new file mode 100644 index 000000000..8a475b863 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/client/package-info.java @@ -0,0 +1,12 @@ +/** + * Clientside mixins + */ +@FieldsAreNonnullByDefault +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package org.ladysnake.vaquero.impl.mixin.client; + +import net.minecraft.util.annotation.FieldsAreNonnullByDefault; +import net.minecraft.util.annotation.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityAccessor.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityAccessor.java new file mode 100644 index 000000000..b4299de4c --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityAccessor.java @@ -0,0 +1,28 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin.common; + +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Entity.class) +public interface EntityAccessor { + @Invoker("getJumpVelocityMultiplier") + float requiem$invokeGetJumpVelocityMultiplier(); +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityMixin.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityMixin.java new file mode 100644 index 000000000..5298c9a26 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/EntityMixin.java @@ -0,0 +1,49 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin.common; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(Entity.class) +public abstract class EntityMixin { + @Shadow + public abstract World getWorld(); + + @Shadow + protected abstract void setRotation(float yaw, float pitch); + + @Shadow + public float prevYaw; + + @Shadow + public abstract float getYaw(); + + // Overridden in MobEntityMixin + @WrapOperation(method = {"isLogicalSideForUpdatingMovement", "getControlledVehicle"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPrimaryPassenger()Lnet/minecraft/entity/LivingEntity;")) + protected @Nullable LivingEntity requiem$enablePossessionRiding(Entity instance, Operation original) { + return original.call(instance); + } +} diff --git a/requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ExternalJumpingMountFactory.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityAccessor.java similarity index 67% rename from requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ExternalJumpingMountFactory.java rename to requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityAccessor.java index 812061f53..9878de46e 100644 --- a/requiem-api/src/main/java/ladysnake/requiem/api/v1/internal/ExternalJumpingMountFactory.java +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityAccessor.java @@ -15,13 +15,14 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program; If not, see . */ -package ladysnake.requiem.api.v1.internal; +package org.ladysnake.vaquero.impl.mixin.common; -import dev.onyxstudios.cca.api.v3.component.ComponentFactory; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; import net.minecraft.entity.LivingEntity; -import net.minecraft.sound.SoundEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; -public interface ExternalJumpingMountFactory { - ComponentFactory simple(float baseJumpStrength, SoundEvent stepSound); +@Mixin(LivingEntity.class) +public interface LivingEntityAccessor { + @Accessor + void setJumpingCooldown(int cooldown); } diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityMixin.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityMixin.java new file mode 100644 index 000000000..79b0a0e3a --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/LivingEntityMixin.java @@ -0,0 +1,83 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin.common; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.attribute.EntityAttribute; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.Nullable; +import org.ladysnake.vaquero.impl.mixin.PossessionRidingHelper; +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.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin extends EntityMixin { + @Shadow + public abstract double getAttributeValue(EntityAttribute attribute); + + @Shadow + public float bodyYaw; + + @Shadow + public float headYaw; + + @WrapOperation(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getPrimaryPassenger()Lnet/minecraft/entity/LivingEntity;")) + private @Nullable LivingEntity possessionRiding(LivingEntity instance, Operation original) { + return PossessionRidingHelper.getRider(instance, original.call(instance)); + } + + @WrapOperation(method = "travelControlled", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getControlledMovementInput(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/Vec3d;)Lnet/minecraft/util/math/Vec3d;")) + private Vec3d getControlledMovement(LivingEntity instance, PlayerEntity player, Vec3d input, Operation original) { + return PossessionRidingHelper.getControlledMovement(instance, player, original.call(instance, player, input)); + } + + @ModifyVariable(method = "travel", at = @At("HEAD"), argsOnly = true) + protected Vec3d requiem$travelStart(Vec3d movementInput) { + // overridden in MobEntityMixin + return movementInput; + } + + @Inject(method = "travelControlled", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;tickControlled(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/Vec3d;)V", shift = At.Shift.AFTER)) + protected void requiem$tickControlled(PlayerEntity player, Vec3d input, CallbackInfo ci) { + // Overridden in MobEntityMixin + } + + @Inject(method = "getControlledMovementInput", at = @At("RETURN"), cancellable = true) + private void getControlledMovement(PlayerEntity player, Vec3d input, CallbackInfoReturnable cir) { + if (cir.getReturnValue() == null) { + Vec3d updated = PossessionRidingHelper.getControlledMovement((LivingEntity) (Object) this, player, null); + if (updated != null) { + cir.setReturnValue(updated); + } + } + } + + @SuppressWarnings("CancellableInjectionUsage") + @Inject(method = "getRiddenSpeed", at = @At("RETURN"), cancellable = true) + protected void requiem$getRiddenSpeed(PlayerEntity player, CallbackInfoReturnable cir) { + // Overridden in MobEntityMixin + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/MobEntityMixin.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/MobEntityMixin.java new file mode 100644 index 000000000..9c5f8668c --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/MobEntityMixin.java @@ -0,0 +1,80 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin.common; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.Nullable; +import org.ladysnake.vaquero.api.ExternalJumpingMount; +import org.ladysnake.vaquero.api.events.JumpingMountEvents; +import org.ladysnake.vaquero.api.events.MobTravelRidingCallback; +import org.ladysnake.vaquero.impl.mixin.PossessionRidingHelper; +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(MobEntity.class) +public abstract class MobEntityMixin extends LivingEntityMixin { + /** + * Warning: this injector is very fragile, as it gets overridden in every rideable entity - redundant WrapOperations are done in important places + */ + @Inject(method = "getPrimaryPassenger", at = @At("RETURN"), cancellable = true) + private void getPrimaryPassenger(CallbackInfoReturnable cir) { + if (cir.getReturnValue() == null) { + LivingEntity actualRider = PossessionRidingHelper.getRider((Entity) (Object) this, cir.getReturnValue()); + if (actualRider != null) { + cir.setReturnValue(actualRider); + } + } + } + + @Override + protected Vec3d requiem$travelStart(Vec3d movementInput) { + LivingEntity self = (LivingEntity) (Object) this; + if (JumpingMountEvents.FIND_ENTITY_JUMP.invoker().findJumpingMount(self) instanceof ExternalJumpingMount jumpingMount) { + jumpingMount.attemptJump(); + } + + return movementInput; + } + + @Override + protected @Nullable LivingEntity requiem$enablePossessionRiding(Entity instance, Operation original) { + return PossessionRidingHelper.getRider(instance, original.call(instance)); + } + + @Override + protected void requiem$getRiddenSpeed(PlayerEntity player, CallbackInfoReturnable cir) { + if (MobTravelRidingCallback.EVENT.invoker().canBeControlled((MobEntity) (Object) this, player)) { + cir.setReturnValue((float)this.getAttributeValue(EntityAttributes.GENERIC_MOVEMENT_SPEED)); + } + } + + @Override + protected void requiem$tickControlled(PlayerEntity player, Vec3d input, CallbackInfo ci) { + this.setRotation(player.getYaw(), player.getPitch() * 0.5F); + this.prevYaw = this.bodyYaw = this.headYaw = this.getYaw(); + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/ServerPlayNetworkHandlerMixin.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/ServerPlayNetworkHandlerMixin.java new file mode 100644 index 000000000..3b401506c --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/ServerPlayNetworkHandlerMixin.java @@ -0,0 +1,64 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package org.ladysnake.vaquero.impl.mixin.common; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.entity.Entity; +import net.minecraft.entity.JumpingMount; +import net.minecraft.entity.LivingEntity; +import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import org.ladysnake.vaquero.api.events.JumpingMountEvents; +import org.ladysnake.vaquero.impl.mixin.PossessionRidingHelper; +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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerPlayNetworkHandler.class) +public abstract class ServerPlayNetworkHandlerMixin { + @Shadow + public ServerPlayerEntity player; + + @WrapOperation(method = "onVehicleMove", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPrimaryPassenger()Lnet/minecraft/entity/LivingEntity;")) + private LivingEntity enableRiding(Entity instance, Operation original) { + return PossessionRidingHelper.getRider(instance, original.call(instance)); + } + + @Inject(method = "onClientCommand", at = @At("HEAD")) + private void swapJumpingMount(ClientCommandC2SPacket packet, CallbackInfo ci) { + if (packet.getMode() == ClientCommandC2SPacket.Mode.START_RIDING_JUMP || packet.getMode() == ClientCommandC2SPacket.Mode.STOP_RIDING_JUMP) { + if (!(this.player.getVehicle() instanceof JumpingMount)) { + JumpingMount jumpingMount = JumpingMountEvents.FIND_ENTITY_JUMP.invoker().findJumpingMount(player); + if (jumpingMount != null) { + if (packet.getMode() == ClientCommandC2SPacket.Mode.START_RIDING_JUMP) { + int i = packet.getMountJumpHeight(); + if (jumpingMount.canJump() && i > 0) { + jumpingMount.startJumping(i); + } + } else { + jumpingMount.stopJumping(); + } + } + } + } + } +} diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/package-info.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/package-info.java new file mode 100644 index 000000000..b4c0cd6c8 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/common/package-info.java @@ -0,0 +1,12 @@ +/** + * Mixins that apply on both sides + */ +@FieldsAreNonnullByDefault +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package org.ladysnake.vaquero.impl.mixin.common; + +import net.minecraft.util.annotation.FieldsAreNonnullByDefault; +import net.minecraft.util.annotation.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/package-info.java b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/package-info.java new file mode 100644 index 000000000..e52576dd0 --- /dev/null +++ b/requiem-core/vaquero/src/main/java/org/ladysnake/vaquero/impl/mixin/package-info.java @@ -0,0 +1,12 @@ +/** + * Classes implementing behaviours defined in the API + */ +@FieldsAreNonnullByDefault +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package org.ladysnake.vaquero.impl.mixin; + +import net.minecraft.util.annotation.FieldsAreNonnullByDefault; +import net.minecraft.util.annotation.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/requiem-core/vaquero/src/main/resources/mixins.vaquero.client.json b/requiem-core/vaquero/src/main/resources/mixins.vaquero.client.json new file mode 100644 index 000000000..e92a2f68f --- /dev/null +++ b/requiem-core/vaquero/src/main/resources/mixins.vaquero.client.json @@ -0,0 +1,9 @@ +{ + "parent": "mixins.vaquero.common.json", + "package": "org.ladysnake.vaquero.impl.mixin.client", + "mixins": [ + ], + "client": [ + "ClientPlayerEntityMixin" + ] +} diff --git a/requiem-core/vaquero/src/main/resources/mixins.vaquero.common.json b/requiem-core/vaquero/src/main/resources/mixins.vaquero.common.json new file mode 100644 index 000000000..4c2a6a16c --- /dev/null +++ b/requiem-core/vaquero/src/main/resources/mixins.vaquero.common.json @@ -0,0 +1,17 @@ +{ + "required": true, + "package": "org.ladysnake.vaquero.impl.mixin.common", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.7.11-SNAPSHOT", + "mixins": [ + "EntityAccessor", + "EntityMixin", + "LivingEntityAccessor", + "LivingEntityMixin", + "MobEntityMixin", + "ServerPlayNetworkHandlerMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/requiem-core/vaquero/src/main/resources/quilt.mod.json b/requiem-core/vaquero/src/main/resources/quilt.mod.json new file mode 100644 index 000000000..4aa1384f2 --- /dev/null +++ b/requiem-core/vaquero/src/main/resources/quilt.mod.json @@ -0,0 +1,42 @@ +{ + "schema_version": 1, + "quilt_loader": { + "group": "org.ladysnake", + "id": "vaquero", + "version": "${version}", + "metadata": { + "name": "Vaquero", + "description": "Library for riding anything", + "license": "LGPL-3.0-or-later", + "contributors": { + "Pyrofab": "Owner" + }, + "contact": { + "sources": "https://github.com/Ladysnake/Requiem", + "issues": "https://github.com/Ladysnake/Requiem/issues", + "discord": "https://discord.ladysnake.org" + } + }, + "intermediate_mappings": "net.fabricmc:intermediary", + "entrypoints": { + "init": "org.ladysnake.vaquero.impl.Vaquero" + } + }, + "environment": "*", + "mixin": [ + { + "config": "mixins.vaquero.client.json", + "environment": "client" + }, + "mixins.vaquero.common.json" + ], + "modmenu": { + "parent": { + "id": "requiem", + "name": "Requiem", + "description": "Death revamped and ethereal powers", + "icon": "skull_logo.png" + }, + "badges": [ "library" ] + } +} diff --git a/requiem-core/vaquero/src/main/resources/skull_logo.png b/requiem-core/vaquero/src/main/resources/skull_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d1824c52ff91457581e387687dc59a5dd94673dc GIT binary patch literal 541 zcmV+&0^Zl0N#_X#>$!fee!XvFn%gv3a7780UEul|j=KTd$;n!Xx7gVkrSyyd zAq)!3aGYbK5Cv)WAVeO5ov7Lzr8NSI#Vkc8M#jPz7;2#D6X~zg=(q|do-|=9c@4Im z$L^1Dp8XZ@eRr9{Zy1POLPzI0Je#KYr1joNJ?`B_9>&CEGZM)blu9MI zt_#bupzAuO5;u7BZKTt!l%5gbAvSy+gRv%-etv$jgLAkW;C&kp-Mv>iKn?NX7W73g zGc1J3r*~u*(MOGx`1QU`6@3pw*x%n{dHi{SORu`TGN26*RYaooNX^_te54tX{)?n) f>uQq!4%8h13#cvN^h)2>00000NkvXXu0mjfp`iNU literal 0 HcmV?d00001 diff --git a/settings.gradle b/settings.gradle index ad64b6440..9ebcefe9b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,6 +21,7 @@ rootProject.name = 'requiem' include "requiem-api" include "requiem-core" +include "requiem-core:vaquero" ['pandemonium'].forEach { include it diff --git a/src/main/java/ladysnake/requiem/common/ApiInitializer.java b/src/main/java/ladysnake/requiem/common/ApiInitializer.java index 73189f8ab..0ddbe5594 100644 --- a/src/main/java/ladysnake/requiem/common/ApiInitializer.java +++ b/src/main/java/ladysnake/requiem/common/ApiInitializer.java @@ -34,19 +34,15 @@ */ package ladysnake.requiem.common; -import dev.onyxstudios.cca.api.v3.component.ComponentFactory; import ladysnake.requiem.api.v1.RequiemApi; import ladysnake.requiem.api.v1.RequiemPlugin; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; import ladysnake.requiem.api.v1.entity.InventoryLimiter; import ladysnake.requiem.api.v1.entity.ability.MobAbilityConfig; import ladysnake.requiem.api.v1.entity.ability.MobAbilityRegistry; import ladysnake.requiem.api.v1.internal.ApiInternals; -import ladysnake.requiem.api.v1.internal.ExternalJumpingMountFactory; import ladysnake.requiem.api.v1.remnant.SoulbindingRegistry; import ladysnake.requiem.api.v1.util.SubDataManager; import ladysnake.requiem.api.v1.util.SubDataManagerHelper; -import ladysnake.requiem.common.possession.jump.DummyJumpingMount; import ladysnake.requiem.core.RequiemCore; import ladysnake.requiem.core.ability.DefaultedMobAbilityRegistry; import ladysnake.requiem.core.ability.ImmutableMobAbilityConfig; @@ -58,8 +54,6 @@ import ladysnake.requiem.core.util.reflection.ReflectionHelper; import ladysnake.requiem.core.util.reflection.UncheckedReflectionException; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.entity.LivingEntity; -import net.minecraft.sound.SoundEvent; import net.minecraft.world.World; import org.apiguardian.api.API; import org.ladysnake.locki.Locki; @@ -78,13 +72,6 @@ public static void init() { try { ReflectionHelper.>>setField(ApiInternals.class.getDeclaredField("abilityBuilderFactory"), ImmutableMobAbilityConfig.Builder::new); - ReflectionHelper.setField(ApiInternals.class.getDeclaredField("externalJumpingMountFactory"), - new ExternalJumpingMountFactory() { - @Override - public ComponentFactory simple(float baseJumpStrength, SoundEvent stepSound) { - return e -> new DummyJumpingMount(e, baseJumpStrength, stepSound); - } - }); ReflectionHelper.setField(ApiInternals.class.getDeclaredField("serverSubDataManagerHelper"), new ServerSubDataManagerHelper()); ReflectionHelper.setField(ApiInternals.class.getDeclaredField("clientSubDataManagerHelper"), diff --git a/src/main/java/ladysnake/requiem/common/RequiemComponents.java b/src/main/java/ladysnake/requiem/common/RequiemComponents.java index 835fe38e6..10efd2dcb 100644 --- a/src/main/java/ladysnake/requiem/common/RequiemComponents.java +++ b/src/main/java/ladysnake/requiem/common/RequiemComponents.java @@ -40,10 +40,10 @@ import dev.onyxstudios.cca.api.v3.scoreboard.ScoreboardComponentFactoryRegistry; import dev.onyxstudios.cca.api.v3.scoreboard.ScoreboardComponentInitializer; import ladysnake.requiem.api.v1.entity.CurableEntityComponent; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; import ladysnake.requiem.api.v1.entity.MovementAlterer; import ladysnake.requiem.api.v1.entity.ability.MobAbilityController; import ladysnake.requiem.api.v1.internal.StatusEffectReapplicator; +import ladysnake.requiem.api.v1.possession.Possessable; import ladysnake.requiem.api.v1.possession.PossessedData; import ladysnake.requiem.api.v1.possession.PossessionComponent; import ladysnake.requiem.api.v1.record.GlobalRecordKeeper; @@ -61,7 +61,6 @@ import ladysnake.requiem.common.entity.effect.StatusEffectReapplicatorImpl; import ladysnake.requiem.common.gamerule.RequiemSyncedGamerules; import ladysnake.requiem.common.possession.LootingPossessedData; -import ladysnake.requiem.common.possession.jump.DummyHorseJumpingMount; import ladysnake.requiem.common.remnant.DroppedVesselTracker; import ladysnake.requiem.common.remnant.GlobalAttritionFocus; import ladysnake.requiem.common.remnant.PlayerBodyTracker; @@ -85,7 +84,13 @@ import net.minecraft.entity.passive.FrogEntity; import net.minecraft.entity.passive.GoatEntity; import net.minecraft.entity.passive.HorseBaseEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.sound.SoundEvents; +import org.jetbrains.annotations.Nullable; +import org.ladysnake.vaquero.api.ExternalJumpingMount; +import org.ladysnake.vaquero.impl.jump.DummyHorseJumpingMount; + +import java.util.function.Function; public final class RequiemComponents implements EntityComponentInitializer, ScoreboardComponentInitializer { @@ -112,9 +117,10 @@ public void registerEntityComponentFactories(EntityComponentFactoryRegistry regi registry.registerForPlayers(PlayerBodyTracker.KEY, PlayerBodyTracker::new, RespawnCopyStrategy.ALWAYS_COPY); registry.registerForPlayers(PenanceComponent.KEY, PenanceComponent::new, RespawnCopyStrategy.LOSSLESS_ONLY); registry.registerFor(LivingEntity.class, SoulHolderComponent.KEY, SoulHolderComponent::new); - registry.registerFor(FrogEntity.class, ExternalJumpingMount.KEY, ExternalJumpingMount.simple(0.6F, SoundEvents.ENTITY_FROG_STEP)); - registry.registerFor(GoatEntity.class, ExternalJumpingMount.KEY, ExternalJumpingMount.simple(1F, SoundEvents.ENTITY_GOAT_STEP)); - registry.registerFor(HorseBaseEntity.class, ExternalJumpingMount.KEY, e -> new DummyHorseJumpingMount(e, SoundEvents.ENTITY_HORSE_STEP)); + Function getPossessor = e -> ((Possessable) e).getPossessor(); + registry.registerFor(FrogEntity.class, ExternalJumpingMount.KEY, ExternalJumpingMount.simple(0.6F, SoundEvents.ENTITY_FROG_STEP, getPossessor)); + registry.registerFor(GoatEntity.class, ExternalJumpingMount.KEY, ExternalJumpingMount.simple(1F, SoundEvents.ENTITY_GOAT_STEP, getPossessor)); + registry.registerFor(HorseBaseEntity.class, ExternalJumpingMount.KEY, e -> new DummyHorseJumpingMount(e, SoundEvents.ENTITY_HORSE_STEP, getPossessor)); registry.registerForPlayers(RiftTracker.KEY, PlayerRiftTracker::new, RespawnCopyStrategy.ALWAYS_COPY); registry.registerForPlayers(DroppedVesselTracker.KEY, DroppedVesselTracker::new, RespawnCopyStrategy.LOSSLESS_ONLY); } diff --git a/src/main/java/ladysnake/requiem/common/VanillaRequiemPlugin.java b/src/main/java/ladysnake/requiem/common/VanillaRequiemPlugin.java index a175231ab..0bf3d877d 100644 --- a/src/main/java/ladysnake/requiem/common/VanillaRequiemPlugin.java +++ b/src/main/java/ladysnake/requiem/common/VanillaRequiemPlugin.java @@ -48,7 +48,6 @@ import ladysnake.requiem.api.v1.entity.ability.MobAbilityRegistry; import ladysnake.requiem.api.v1.event.minecraft.AllowUseEntityCallback; import ladysnake.requiem.api.v1.event.minecraft.LivingEntityDropCallback; -import ladysnake.requiem.api.v1.event.minecraft.MobTravelRidingCallback; import ladysnake.requiem.api.v1.event.minecraft.PlayerRespawnCallback; import ladysnake.requiem.api.v1.event.minecraft.PrepareRespawnCallback; import ladysnake.requiem.api.v1.event.requiem.CanCurePossessedCallback; @@ -96,7 +95,6 @@ import ladysnake.requiem.common.gamerule.PossessionDetection; import ladysnake.requiem.common.gamerule.RequiemGamerules; import ladysnake.requiem.common.network.RequiemNetworking; -import ladysnake.requiem.common.possession.MobRidingType; import ladysnake.requiem.common.remnant.BasePossessionHandlers; import ladysnake.requiem.common.remnant.PlayerSplitter; import ladysnake.requiem.common.remnant.RemnantTypes; @@ -144,6 +142,9 @@ import org.jetbrains.annotations.Nullable; import org.ladysnake.locki.DefaultInventoryNodes; import org.ladysnake.locki.ModdedInventoryNodes; +import org.ladysnake.vaquero.api.MobRidingType; +import org.ladysnake.vaquero.api.events.JumpingMountEvents; +import org.ladysnake.vaquero.api.events.MobTravelRidingCallback; import javax.annotation.Nonnull; import java.util.HashMap; @@ -375,6 +376,10 @@ private void registerPossessionEventHandlers() { }; }; }); + JumpingMountEvents.FIND_PLAYER_JUMP.register(entity -> { + MobEntity host = PossessionComponent.getHost(entity); + return host == null ? null : JumpingMountEvents.FIND_ENTITY_JUMP.invoker().findJumpingMount(host); + }); } private void refreshInventoryLocks(PlayerEntity player, @Nullable MobEntity possessed) { diff --git a/src/main/java/ladysnake/requiem/common/possession/MobRidingType.java b/src/main/java/ladysnake/requiem/common/possession/MobRidingType.java deleted file mode 100644 index 93a59d1ae..000000000 --- a/src/main/java/ladysnake/requiem/common/possession/MobRidingType.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Requiem - * Copyright (C) 2017-2024 Ladysnake - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Linking this mod statically or dynamically with other - * modules is making a combined work based on this mod. - * Thus, the terms and conditions of the GNU General Public License cover the whole combination. - * - * In addition, as a special exception, the copyright holders of - * this mod give you permission to combine this mod - * with free software programs or libraries that are released under the GNU LGPL - * and with code included in the standard release of Minecraft under All Rights Reserved (or - * modified versions of such code, with unchanged license). - * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the other code concerned. - * - * Note that people who make modified versions of this mod are not obligated to grant - * this special exception for their modified versions; it is their choice whether to do so. - * The GNU General Public License gives permission to release a modified version without this exception; - * this exception also makes it possible to release a modified version which carries forward this exception. - */ -package ladysnake.requiem.common.possession; - -import ladysnake.requiem.common.tag.RequiemEntityTypeTags; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.mob.RavagerEntity; -import net.minecraft.entity.mob.SkeletonEntity; -import net.minecraft.entity.mob.SpiderEntity; -import net.minecraft.entity.passive.ChickenEntity; -import net.minecraft.entity.passive.StriderEntity; -import net.minecraft.registry.tag.EntityTypeTags; - -public enum MobRidingType { - DEFAULT, MOUNT, RIDE; - - public boolean canMount() { - return this != DEFAULT; - } - - public boolean canSteer() { - return this == RIDE; - } - - public static MobRidingType get(Entity entity, LivingEntity possessed) { - if (entity instanceof SpiderEntity) { - return possessed instanceof SkeletonEntity ? MOUNT : DEFAULT; - } else if (entity instanceof RavagerEntity) { - return possessed.getType().isIn(EntityTypeTags.RAIDERS) ? RIDE : DEFAULT; - } else if (entity instanceof ChickenEntity) { - return possessed.getType().isIn(RequiemEntityTypeTags.ZOMBIES) && possessed.isBaby() ? RIDE : DEFAULT; - } else if (entity instanceof StriderEntity) { - return possessed.getType() == EntityType.ZOMBIFIED_PIGLIN || possessed.getType().isIn(RequiemEntityTypeTags.PIGLINS) ? RIDE : DEFAULT; - } - - return DEFAULT; - } -} diff --git a/src/main/java/ladysnake/requiem/common/possession/jump/DummyHorseJumpingMount.java b/src/main/java/ladysnake/requiem/common/possession/jump/DummyHorseJumpingMount.java deleted file mode 100644 index b5cee4826..000000000 --- a/src/main/java/ladysnake/requiem/common/possession/jump/DummyHorseJumpingMount.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Requiem - * Copyright (C) 2017-2024 Ladysnake - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Linking this mod statically or dynamically with other - * modules is making a combined work based on this mod. - * Thus, the terms and conditions of the GNU General Public License cover the whole combination. - * - * In addition, as a special exception, the copyright holders of - * this mod give you permission to combine this mod - * with free software programs or libraries that are released under the GNU LGPL - * and with code included in the standard release of Minecraft under All Rights Reserved (or - * modified versions of such code, with unchanged license). - * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the other code concerned. - * - * Note that people who make modified versions of this mod are not obligated to grant - * this special exception for their modified versions; it is their choice whether to do so. - * The GNU General Public License gives permission to release a modified version without this exception; - * this exception also makes it possible to release a modified version which carries forward this exception. - */ -package ladysnake.requiem.common.possession.jump; - -import net.minecraft.entity.passive.HorseBaseEntity; -import net.minecraft.sound.SoundEvent; - -public class DummyHorseJumpingMount extends DummyJumpingMount { - public DummyHorseJumpingMount(HorseBaseEntity mob, SoundEvent stepSound) { - super(mob, -1, stepSound); - } - - @Override - protected double getBaseJumpingStrength() { - return ((HorseBaseEntity) this.mob).getJumpStrength(); - } -} diff --git a/src/main/java/ladysnake/requiem/common/possession/jump/DummyNoDragJumpingMount.java b/src/main/java/ladysnake/requiem/common/possession/jump/DummyNoDragJumpingMount.java deleted file mode 100644 index 805759c35..000000000 --- a/src/main/java/ladysnake/requiem/common/possession/jump/DummyNoDragJumpingMount.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Requiem - * Copyright (C) 2017-2024 Ladysnake - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Linking this mod statically or dynamically with other - * modules is making a combined work based on this mod. - * Thus, the terms and conditions of the GNU General Public License cover the whole combination. - * - * In addition, as a special exception, the copyright holders of - * this mod give you permission to combine this mod - * with free software programs or libraries that are released under the GNU LGPL - * and with code included in the standard release of Minecraft under All Rights Reserved (or - * modified versions of such code, with unchanged license). - * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the other code concerned. - * - * Note that people who make modified versions of this mod are not obligated to grant - * this special exception for their modified versions; it is their choice whether to do so. - * The GNU General Public License gives permission to release a modified version without this exception; - * this exception also makes it possible to release a modified version which carries forward this exception. - */ -package ladysnake.requiem.common.possession.jump; - -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.sound.SoundEvent; - -/** - * Currently unused because setting noDrag means you have to revert it when dissociating and lazy - * - * But it allows doing epic jumps as a goat - */ -public class DummyNoDragJumpingMount extends DummyJumpingMount { - public DummyNoDragJumpingMount(LivingEntity mob, SoundEvent stepSound) { - super(mob, 1, stepSound); - } - - @Override - protected void beginClientJump(PlayerEntity possessor) { - super.beginClientJump(possessor); - possessor.setNoDrag(true); - } - - @Override - protected void finishClientJump(PlayerEntity possessor) { - super.finishClientJump(possessor); - possessor.setNoDrag(false); - } - - @Override - public void startJumping(int height) { - this.mob.setNoDrag(true); - super.startJumping(height); - } - - @Override - public void stopJumping() { - super.stopJumping(); - this.mob.setNoDrag(false); - } -} diff --git a/src/main/java/ladysnake/requiem/common/remnant/BasePossessionHandlers.java b/src/main/java/ladysnake/requiem/common/remnant/BasePossessionHandlers.java index e3513e203..800417832 100644 --- a/src/main/java/ladysnake/requiem/common/remnant/BasePossessionHandlers.java +++ b/src/main/java/ladysnake/requiem/common/remnant/BasePossessionHandlers.java @@ -36,8 +36,6 @@ import dev.onyxstudios.cca.api.v3.entity.TrackingStartCallback; import ladysnake.requiem.Requiem; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; -import ladysnake.requiem.api.v1.event.minecraft.JumpingMountEvents; import ladysnake.requiem.api.v1.event.minecraft.MobConversionCallback; import ladysnake.requiem.api.v1.event.requiem.PossessionEvents; import ladysnake.requiem.api.v1.event.requiem.PossessionStartCallback; @@ -112,7 +110,6 @@ public static void register() { } return PossessionStartCallback.Result.PASS; }); - JumpingMountEvents.MOUNT_CHECK.register(ExternalJumpingMount.KEY::getNullable); MobConversionCallback.EVENT.register(PossessedDataBase::onMobConverted); MobConversionCallback.EVENT.register((original, converted) -> dropArmorIfBanned(converted)); MobConversionCallback.EVENT.register(SoulHolderComponent::onMobConverted); diff --git a/src/main/java/ladysnake/requiem/common/tag/RequiemEntityTypeTags.java b/src/main/java/ladysnake/requiem/common/tag/RequiemEntityTypeTags.java index f6ec2f7da..63d5c38cb 100644 --- a/src/main/java/ladysnake/requiem/common/tag/RequiemEntityTypeTags.java +++ b/src/main/java/ladysnake/requiem/common/tag/RequiemEntityTypeTags.java @@ -56,8 +56,6 @@ public final class RequiemEntityTypeTags { public static final TagKey> REPLACEABLE_SKELETONS = register("transformation/replaceable_skeletons"); public static final TagKey> SKELETONS = register("skeletons"); - public static final TagKey> ZOMBIES = register("zombies"); - public static final TagKey> PIGLINS = register("piglins"); public static final TagKey> SOUL_AGGREGATES = register("soul_capture/soul_aggregates"); public static final TagKey> SOUL_CAPTURE_BLACKLIST = register("soul_capture/soul_capture_blacklist"); diff --git a/src/main/java/ladysnake/requiem/compat/RequiemCompatibilityManager.java b/src/main/java/ladysnake/requiem/compat/RequiemCompatibilityManager.java index e6c016afc..baf4ddc0b 100644 --- a/src/main/java/ladysnake/requiem/compat/RequiemCompatibilityManager.java +++ b/src/main/java/ladysnake/requiem/compat/RequiemCompatibilityManager.java @@ -39,6 +39,7 @@ import dev.onyxstudios.cca.api.v3.entity.EntityComponentFactoryRegistry; import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy; import ladysnake.requiem.Requiem; +import ladysnake.requiem.api.v1.annotation.CalledThroughReflection; import ladysnake.requiem.api.v1.event.requiem.PlayerShellEvents; import ladysnake.requiem.api.v1.remnant.RemnantComponent; import ladysnake.requiem.common.entity.PlayerShellEntity; @@ -59,7 +60,6 @@ public static void init() { try { load("eldritch_mobs", EldritchMobsCompat.class); load("golemsgalore", GolemsGaloreCompat.class); - // Haema must be loaded before Origins, because vampire data must be stored before the origin gets cleared load("bewitchment", BewitchmentCompat.class); load("origins", OriginsCompat.class); load("snowmercy", SnowMercyCompat.class); @@ -80,6 +80,7 @@ public static void load(String modId, Class action) { } } + @CalledThroughReflection public static void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) { if (QuiltLoader.isModLoaded("origins")) { registry.beginRegistration(PlayerEntity.class, OriginsCompat.APOLI_HOLDER_KEY).respawnStrategy(RespawnCopyStrategy.ALWAYS_COPY).end(p -> new ComponentDataHolder<>(OriginsCompat.APOLI_POWER_KEY, OriginsCompat.APOLI_HOLDER_KEY)); diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/riding/ClientPlayerEntityMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/riding/ClientPlayerEntityMixin.java deleted file mode 100644 index 965464887..000000000 --- a/src/main/java/ladysnake/requiem/mixin/client/possession/riding/ClientPlayerEntityMixin.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Requiem - * Copyright (C) 2017-2024 Ladysnake - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Linking this mod statically or dynamically with other - * modules is making a combined work based on this mod. - * Thus, the terms and conditions of the GNU General Public License cover the whole combination. - * - * In addition, as a special exception, the copyright holders of - * this mod give you permission to combine this mod - * with free software programs or libraries that are released under the GNU LGPL - * and with code included in the standard release of Minecraft under All Rights Reserved (or - * modified versions of such code, with unchanged license). - * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the other code concerned. - * - * Note that people who make modified versions of this mod are not obligated to grant - * this special exception for their modified versions; it is their choice whether to do so. - * The GNU General Public License gives permission to release a modified version without this exception; - * this exception also makes it possible to release a modified version which carries forward this exception. - */ -package ladysnake.requiem.mixin.client.possession.riding; - -import com.mojang.authlib.GameProfile; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; -import ladysnake.requiem.api.v1.event.minecraft.JumpingMountEvents; -import ladysnake.requiem.api.v1.possession.PossessionComponent; -import ladysnake.requiem.core.mixin.access.LivingEntityAccessor; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.JumpingMount; -import net.minecraft.entity.LivingEntity; -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.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ClientPlayerEntity.class) -public class ClientPlayerEntityMixin extends AbstractClientPlayerEntity { - public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) { - super(world, profile); - } - - @Inject(method = "getJumpingMount", at = @At("RETURN"), cancellable = true) - private void hackJumpingMount(CallbackInfoReturnable cir) { - if (cir.getReturnValue() == null && this.getVehicle() == null) { - LivingEntity host = PossessionComponent.getHost(this); - if (host != null) { - JumpingMount jumpingMount = JumpingMountEvents.MOUNT_CHECK.invoker().getJumpingMount(host); - if (jumpingMount != null && jumpingMount.canJump()) { - cir.setReturnValue(jumpingMount); - } - } - } - } - - @ModifyVariable(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I"), allow = 1) - private JumpingMount swapJumpingMount(JumpingMount mount) { - if (mount instanceof ExternalJumpingMount) { - // prevent normal jumps - ((LivingEntityAccessor) this).setJumpingCooldown(10); - } - return mount; - } -} diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/CatEntityMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/CatEntityMixin.java index b8a069df7..92ca5b321 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/CatEntityMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/CatEntityMixin.java @@ -35,11 +35,8 @@ package ladysnake.requiem.mixin.common.possession.gameplay; import net.minecraft.entity.EntityPose; -import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.CatEntity; -import net.minecraft.entity.passive.TameableEntity; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -49,10 +46,6 @@ public abstract class CatEntityMixin extends LivingEntityMixin { @Shadow public abstract void setInSleepingPose(boolean sleeping); - protected CatEntityMixin(EntityType entityType, World world) { - super(entityType, world); - } - @Override protected void requiem$sleep(BlockPos pos, CallbackInfo ci) { this.setPose(EntityPose.STANDING); diff --git a/src/main/java/ladysnake/requiem/mixin/common/access/EntityAccessor.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/EntityMixin.java similarity index 85% rename from src/main/java/ladysnake/requiem/mixin/common/access/EntityAccessor.java rename to src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/EntityMixin.java index 286206b7e..4f4ae498c 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/access/EntityAccessor.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/EntityMixin.java @@ -32,14 +32,19 @@ * The GNU General Public License gives permission to release a modified version without this exception; * this exception also makes it possible to release a modified version which carries forward this exception. */ -package ladysnake.requiem.mixin.common.access; +package ladysnake.requiem.mixin.common.possession.gameplay; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityPose; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.asm.mixin.Shadow; @Mixin(Entity.class) -public interface EntityAccessor { - @Invoker("getJumpVelocityMultiplier") - float requiem$invokeGetJumpVelocityMultiplier(); +public abstract class EntityMixin { + @Shadow + public abstract World getWorld(); + + @Shadow + public abstract void setPose(EntityPose pose); } diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/FoxEntityMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/FoxEntityMixin.java index 665f13cdf..97492f5a1 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/FoxEntityMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/FoxEntityMixin.java @@ -36,11 +36,9 @@ import ladysnake.requiem.api.v1.possession.Possessable; import net.minecraft.entity.EntityPose; -import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.FoxEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -50,10 +48,6 @@ @Mixin(FoxEntity.class) public abstract class FoxEntityMixin extends LivingEntityMixin implements Possessable { - public FoxEntityMixin(EntityType type, World world) { - super(type, world); - } - @Shadow abstract void stopActions(); diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/LivingEntityMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/LivingEntityMixin.java index da60ed8f2..4cce21f36 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/LivingEntityMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/LivingEntityMixin.java @@ -38,22 +38,16 @@ import ladysnake.requiem.api.v1.possession.Possessable; import ladysnake.requiem.common.advancement.criterion.RequiemCriteria; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.objectweb.asm.Opcodes; 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.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -62,37 +56,9 @@ import java.util.UUID; @Mixin(LivingEntity.class) -public abstract class LivingEntityMixin extends Entity implements Possessable { - @Shadow - public float bodyYaw; - - @Shadow - public float headYaw; - +public abstract class LivingEntityMixin extends EntityMixin implements Possessable { private @Nullable UUID requiem$previousPossessorUuid; - @Shadow - public abstract float getMovementSpeed(); - - @Shadow - public abstract double getAttributeValue(EntityAttribute attribute); - - @Shadow - public abstract float getStepHeight(); - - @Shadow - protected abstract float getRiddenSpeed(PlayerEntity player); - - public LivingEntityMixin(EntityType type, World world) { - super(type, world); - } - - @ModifyVariable(method = "travel", at = @At("HEAD"), argsOnly = true) - protected Vec3d requiem$travelStart(Vec3d movementInput) { - // overridden in MobEntityMixin - return movementInput; - } - @Inject(method = "damage", slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;increaseStat(Lnet/minecraft/util/Identifier;I)V"), @@ -105,7 +71,7 @@ private void triggerCriterion(DamageSource source, float amount, CallbackInfoRet if (attacker != null) { PlayerEntity possessor = ((ProtoPossessable) attacker).getPossessor(); if (possessor instanceof ServerPlayerEntity) { - RequiemCriteria.POSSESSED_HIT_ENTITY.handle(((ServerPlayerEntity) possessor), attacker, this, source, dealt, amount, blocked); + RequiemCriteria.POSSESSED_HIT_ENTITY.handle(((ServerPlayerEntity) possessor), attacker, (Entity) (Object) this, source, dealt, amount, blocked); } } } @@ -116,7 +82,7 @@ private void onDeath(DamageSource deathCause, CallbackInfo ci) { PlayerEntity previousPossessor = this.getWorld().getPlayerByUuid(this.requiem$previousPossessorUuid); if (previousPossessor != null) { - RequiemCriteria.DEATH_AFTER_POSSESSION.handle((ServerPlayerEntity) previousPossessor, this, deathCause); + RequiemCriteria.DEATH_AFTER_POSSESSION.handle((ServerPlayerEntity) previousPossessor, (Entity) (Object) this, deathCause); } } } diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/MobEntityMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/MobEntityMixin.java index c1181b1d2..867f535a4 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/MobEntityMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/MobEntityMixin.java @@ -34,90 +34,19 @@ */ package ladysnake.requiem.mixin.common.possession.gameplay; -import ladysnake.requiem.api.v1.entity.ExternalJumpingMount; -import ladysnake.requiem.api.v1.event.minecraft.JumpingMountEvents; -import ladysnake.requiem.api.v1.event.minecraft.MobTravelRidingCallback; import ladysnake.requiem.api.v1.event.requiem.PossessionEvents; import ladysnake.requiem.api.v1.possession.Possessable; import ladysnake.requiem.core.util.DetectionHelper; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.MobEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @SuppressWarnings("UnreachableCode") @Mixin(MobEntity.class) public abstract class MobEntityMixin extends LivingEntityMixin implements Possessable { - private @Nullable Float requiem$previousStepHeight; - - @Shadow - public abstract void setMovementSpeed(float movementSpeed); - - public MobEntityMixin(EntityType type, World world) { - super(type, world); - } - - @Override - protected Vec3d requiem$travelStart(Vec3d movementInput) { - if (this.requiem$previousStepHeight != null) { - this.setStepHeight(this.requiem$previousStepHeight); - this.requiem$previousStepHeight = null; - } - - LivingEntity self = (LivingEntity) (Object) this; - if (JumpingMountEvents.MOUNT_CHECK.invoker().getJumpingMount(self) instanceof ExternalJumpingMount jumpingMount) { - jumpingMount.attemptJump(); - } - - // Straight up copied from HorseBaseEntity#travel - // Also replaces canBeControlledByRider and getPrimaryPassenger with more generic alternatives - if (this.isAlive() && this.hasPassengers()) { - Entity primaryPassenger = this.getPrimaryPassenger(); - Entity passenger = primaryPassenger != null ? primaryPassenger : this.getFirstPassenger(); - - if (!(passenger instanceof LivingEntity livingEntity) || !MobTravelRidingCallback.EVENT.invoker().canBeControlled((MobEntity) (Object) this, livingEntity)) { - return movementInput; - } - - this.setYaw(livingEntity.getYaw()); - this.prevYaw = this.getYaw(); - this.setPitch(livingEntity.getPitch() * 0.5F); - this.setRotation(this.getYaw(), this.getPitch()); - this.bodyYaw = this.getYaw(); - this.headYaw = this.bodyYaw; - - if (this.getStepHeight() < 1.0F) { - this.requiem$previousStepHeight = this.getStepHeight(); - this.setStepHeight(1.0F); - } - - float sidewaysSpeed = livingEntity.sidewaysSpeed * 0.5F; - float forwardSpeed = livingEntity.forwardSpeed; - if (forwardSpeed <= 0.0F) { - forwardSpeed *= 0.25F; - } - - // isLogicalSideForUpdatingMovement but inlined - if (passenger instanceof PlayerEntity player && player.isMainPlayer() || !this.getWorld().isClient()) { - float speed = this.getRiddenSpeed(passenger instanceof PlayerEntity ? (PlayerEntity) passenger : getPossessor()); - this.setMovementSpeed(speed); - return new Vec3d(sidewaysSpeed, movementInput.y, forwardSpeed); - } else if (livingEntity instanceof PlayerEntity) { - this.setVelocity(Vec3d.ZERO); - } - } - return movementInput; - } - @Override public void requiem$pushed(Entity pushed, CallbackInfo ci) { MobEntity self = (MobEntity) (Object) this; diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerPlayNetworkHandlerMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerPlayNetworkHandlerMixin.java deleted file mode 100644 index 7256ec19e..000000000 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerPlayNetworkHandlerMixin.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Requiem - * Copyright (C) 2017-2024 Ladysnake - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Linking this mod statically or dynamically with other - * modules is making a combined work based on this mod. - * Thus, the terms and conditions of the GNU General Public License cover the whole combination. - * - * In addition, as a special exception, the copyright holders of - * this mod give you permission to combine this mod - * with free software programs or libraries that are released under the GNU LGPL - * and with code included in the standard release of Minecraft under All Rights Reserved (or - * modified versions of such code, with unchanged license). - * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the other code concerned. - * - * Note that people who make modified versions of this mod are not obligated to grant - * this special exception for their modified versions; it is their choice whether to do so. - * The GNU General Public License gives permission to release a modified version without this exception; - * this exception also makes it possible to release a modified version which carries forward this exception. - */ -package ladysnake.requiem.mixin.common.possession.gameplay; - -import ladysnake.requiem.api.v1.event.minecraft.JumpingMountEvents; -import ladysnake.requiem.api.v1.possession.PossessionComponent; -import net.minecraft.entity.JumpingMount; -import net.minecraft.entity.LivingEntity; -import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; -import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.server.network.ServerPlayerEntity; -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin { - @Shadow - public ServerPlayerEntity player; - - @Inject(method = "onClientCommand", at = @At("HEAD")) - private void swapJumpingMount(ClientCommandC2SPacket packet, CallbackInfo ci) { - if (packet.getMode() == ClientCommandC2SPacket.Mode.START_RIDING_JUMP || packet.getMode() == ClientCommandC2SPacket.Mode.STOP_RIDING_JUMP) { - if (!(this.player.getVehicle() instanceof JumpingMount)) { - LivingEntity host = PossessionComponent.getHost(this.player); - if (host != null) { - JumpingMount jumpingMount = JumpingMountEvents.MOUNT_CHECK.invoker().getJumpingMount(host); - if (jumpingMount != null) { - if (packet.getMode() == ClientCommandC2SPacket.Mode.START_RIDING_JUMP) { - int i = packet.getMountJumpHeight(); - if (jumpingMount.canJump() && i > 0) { - jumpingMount.startJumping(i); - } - } else { - jumpingMount.stopJumping(); - } - } - } - } - } - } -} diff --git a/src/main/resources/mixins.requiem.client.json b/src/main/resources/mixins.requiem.client.json index c963c0cc8..e04c707d1 100644 --- a/src/main/resources/mixins.requiem.client.json +++ b/src/main/resources/mixins.requiem.client.json @@ -33,7 +33,6 @@ "possession.nightvision.LightmapTextureManagerMixin", "possession.render.GuardianEntityRendererMixin", "possession.render.ShulkerEntityModelMixin", - "possession.riding.ClientPlayerEntityMixin", "remnant.BlabberDialogueScreenMixin", "remnant.ClientPlayerEntityMixin", "remnant.ClientPlayerInteractionManagerMixin", diff --git a/src/main/resources/mixins.requiem.common.json b/src/main/resources/mixins.requiem.common.json index 49ed92f84..80fc7ff75 100644 --- a/src/main/resources/mixins.requiem.common.json +++ b/src/main/resources/mixins.requiem.common.json @@ -8,7 +8,6 @@ "access.ArrowShooter", "access.BrainAccessor", "access.EndermanEntityAccessor", - "access.EntityAccessor", "access.LootContextTypesAccessor", "access.PrepareRamTaskAccessor", "access.ProjectileEntityAccessor", @@ -47,6 +46,7 @@ "possession.gameplay.CreeperEntityMixin", "possession.gameplay.CrossbowItemMixin", "possession.gameplay.EndermanEntityMixin", + "possession.gameplay.EntityMixin", "possession.gameplay.FoxEntityMixin", "possession.gameplay.FrogEntityMixin", "possession.gameplay.HorseBaseEntityMixin", @@ -60,7 +60,6 @@ "possession.gameplay.PigEntityMixin", "possession.gameplay.PlayerEntityMixin", "possession.gameplay.RavagerEntityMixin", - "possession.gameplay.ServerPlayNetworkHandlerMixin", "possession.gameplay.TridentItemMixin", "possession.gameplay.VillagerEntityMixin", "possession.gameplay.WitchEntityMixin",