diff --git a/api/build.gradle b/api/build.gradle index 109c9d3..dfeeba5 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -63,7 +63,7 @@ java { // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. // If you remove this line, sources will not be generated. - withSourcesJar() +// withSourcesJar() sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 diff --git a/api/src/main/java/com/fqf/mario_qua_mario/interfaces/IStompableEntity.java b/api/src/main/java/com/fqf/mario_qua_mario/interfaces/IStompableEntity.java new file mode 100644 index 0000000..5cb3c7a --- /dev/null +++ b/api/src/main/java/com/fqf/mario_qua_mario/interfaces/IStompableEntity.java @@ -0,0 +1,75 @@ +package com.fqf.mario_qua_mario.interfaces; + +import com.fqf.mario_qua_mario.mariodata.IMarioAuthoritativeData; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.Saddleable; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.damage.DamageType; +import net.minecraft.entity.vehicle.AbstractMinecartEntity; +import net.minecraft.entity.vehicle.MinecartEntity; +import net.minecraft.entity.vehicle.VehicleEntity; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.util.Identifier; + +/** + * An entity can implement this interface and override its methods to change Stomp attacks interact with it. + */ +public interface IStompableEntity { + default StompResult mqm$getStompResult( + IMarioAuthoritativeData mario, + Identifier stompType, + boolean canMount, + DamageSource damageSource, + float amount + ) { + // Only entities can be stomped. + if(!(this instanceof Entity entity)) return StompResult.FAIL; + + // Mario can mount some entities by falling onto them from above, like how he mounts Yoshi in most games. + if(canMount && this.mqm$isStompMountable() && mario.getMario().startRiding(entity, false)) + return StompResult.MOUNT; + + // Various datapack-tag-driven interactions + if(entity.getType().isIn(UNSTOMPABLE_ENTITIES)) return StompResult.FAIL; + if(entity.getType().isIn(HURTS_TO_STOMP_ENTITIES)) return StompResult.PAINFUL; + if(entity.getType().isIn(IMMUNE_TO_BASIC_STOMP_ENTITIES) && damageSource.isIn(BASIC_STOMPS)) return StompResult.FAIL; + + // Attempt to apply the damage from the stomp to the entity. + // If the damage goes through, then Mario should do a normal stomp. + // If it doesn't, that means the entity is probably immune for whatever reason, and Mario should do a Resisted stomp. + boolean damaged = entity.damage(damageSource, amount); + + if(damaged) return StompResult.NORMAL; + else return StompResult.RESISTED; + } + + default boolean mqm$isStompMountable() { + if(this instanceof VehicleEntity vehicle) { + // If we're a vehicle, then: + // - If we're a Minecart, then return true if we're an empty minecart (as opposed to, i.e., a Chest Minecart) + // - If we're not a Minecart, then return true + return !(vehicle instanceof MinecartEntity minecart) || minecart.getMinecartType() != AbstractMinecartEntity.Type.RIDEABLE; + } + if(this instanceof Saddleable saddleable) { + // If we're something that can be saddled, then: + // - If we're saddled, then return true + // - If we're not saddled, then return false + return saddleable.isSaddled(); + } + + // If we're neither a vehicle nor saddleable, then return false. + return false; + } + + TagKey> UNSTOMPABLE_ENTITIES = + TagKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of("mario_qua_mario:unstompable")); + TagKey> HURTS_TO_STOMP_ENTITIES = + TagKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of("mario_qua_mario:hurts_to_stomp")); + TagKey> IMMUNE_TO_BASIC_STOMP_ENTITIES = + TagKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of("mario_qua_mario:immune_to_basic_stomp")); + + TagKey BASIC_STOMPS = + TagKey.of(RegistryKeys.DAMAGE_TYPE, Identifier.of("mario_qua_mario:basic_stomps")); +} diff --git a/api/src/main/java/com/fqf/mario_qua_mario/interfaces/StompResult.java b/api/src/main/java/com/fqf/mario_qua_mario/interfaces/StompResult.java new file mode 100644 index 0000000..3200032 --- /dev/null +++ b/api/src/main/java/com/fqf/mario_qua_mario/interfaces/StompResult.java @@ -0,0 +1,10 @@ +package com.fqf.mario_qua_mario.interfaces; + +public enum StompResult { + NORMAL, + PAINFUL, + GLANCING, + RESISTED, + FAIL, + MOUNT +} diff --git a/api/src/main/java/com/fqf/mario_qua_mario/mixin/EntityMixin.java b/api/src/main/java/com/fqf/mario_qua_mario/mixin/EntityMixin.java new file mode 100644 index 0000000..e1c3100 --- /dev/null +++ b/api/src/main/java/com/fqf/mario_qua_mario/mixin/EntityMixin.java @@ -0,0 +1,9 @@ +package com.fqf.mario_qua_mario.mixin; + +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Entity.class) +public abstract class EntityMixin { + +} diff --git a/api/src/main/java/com/fqf/mario_qua_mario/mixin/ExampleMixin.java b/api/src/main/java/com/fqf/mario_qua_mario/mixin/ExampleMixin.java deleted file mode 100644 index 9fee9b0..0000000 --- a/api/src/main/java/com/fqf/mario_qua_mario/mixin/ExampleMixin.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fqf.mario_qua_mario.mixin; - -import net.minecraft.server.MinecraftServer; -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; - -@Mixin(MinecraftServer.class) -public class ExampleMixin { - @Inject(at = @At("HEAD"), method = "loadWorld") - private void init(CallbackInfo info) { - // This code is injected into the start of MinecraftServer.loadWorld()V - } -} \ No newline at end of file diff --git a/api/src/main/resources/mario_qua_mario_api.mixins.json b/api/src/main/resources/mario_qua_mario_api.mixins.json index c924f66..5767fb0 100644 --- a/api/src/main/resources/mario_qua_mario_api.mixins.json +++ b/api/src/main/resources/mario_qua_mario_api.mixins.json @@ -3,7 +3,7 @@ "package": "com.fqf.mario_qua_mario.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "ExampleMixin" + "EntityMixin" ], "injectors": { "defaultRequire": 1 diff --git a/content/build.gradle b/content/build.gradle index 44ac1f6..f6a4fb1 100644 --- a/content/build.gradle +++ b/content/build.gradle @@ -65,7 +65,7 @@ java { // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. // If you remove this line, sources will not be generated. - withSourcesJar() +// withSourcesJar() sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 diff --git a/content/src/main/java/com/fqf/mario_qua_mario/MarioQuaMarioContent.java b/content/src/main/java/com/fqf/mario_qua_mario/MarioQuaMarioContent.java index eeb9d9f..9d99e63 100644 --- a/content/src/main/java/com/fqf/mario_qua_mario/MarioQuaMarioContent.java +++ b/content/src/main/java/com/fqf/mario_qua_mario/MarioQuaMarioContent.java @@ -17,4 +17,7 @@ public void onInitialize() { public static Identifier makeID(String path) { return Identifier.of("mqm", path); } + public static Identifier makeResID(String path) { + return Identifier.of("mario_qua_mario", path); + } } \ No newline at end of file diff --git a/content/src/main/java/com/fqf/mario_qua_mario/powerups/Small.java b/content/src/main/java/com/fqf/mario_qua_mario/powerups/Small.java index b4461d5..acbd2fb 100644 --- a/content/src/main/java/com/fqf/mario_qua_mario/powerups/Small.java +++ b/content/src/main/java/com/fqf/mario_qua_mario/powerups/Small.java @@ -48,23 +48,21 @@ public class Small implements PowerUpDefinition { } @Override public @NotNull PowerHeart getPowerHeart(PowerHeartHelper helper) { - String namespace = "mario_qua_mario"; - return new PowerUpDefinition.PowerHeart( - Identifier.of(namespace, "hud/power_hearts/small/full"), - Identifier.of(namespace, "hud/power_hearts/small/full_blinking"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/full"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/full_blinking"), - Identifier.of(namespace, "hud/power_hearts/small/half"), - Identifier.of(namespace, "hud/power_hearts/small/half_blinking"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/half"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/half_blinking"), - Identifier.of(namespace, "hud/power_hearts/small/hardcore/full"), - Identifier.of(namespace, "hud/power_hearts/small/hardcore/full_blinking"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/hardcore/full"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/hardcore/full_blinking"), - Identifier.of(namespace, "hud/power_hearts/small/hardcore/half"), - Identifier.of(namespace, "hud/power_hearts/small/hardcore/half_blinking"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/hardcore/half"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/hardcore/half_blinking"), - Identifier.of(namespace, "hud/power_hearts/small/container"), - Identifier.of(namespace, "hud/power_hearts/small/container_blinking") + MarioQuaMarioContent.makeResID("hud/power_hearts/small/container"), + MarioQuaMarioContent.makeResID("hud/power_hearts/small/container_blinking") ); } diff --git a/mod/src/main/java/com/fqf/mario_qua_mario/MarioQuaMario.java b/mod/src/main/java/com/fqf/mario_qua_mario/MarioQuaMario.java index da09a30..5e3d214 100644 --- a/mod/src/main/java/com/fqf/mario_qua_mario/MarioQuaMario.java +++ b/mod/src/main/java/com/fqf/mario_qua_mario/MarioQuaMario.java @@ -25,4 +25,7 @@ public void onInitialize() { public static Identifier makeID(String path) { return Identifier.of("mqm", path); } + public static Identifier makeResID(String path) { + return Identifier.of(MOD_ID, path); + } } \ No newline at end of file diff --git a/mod/src/main/java/com/fqf/mario_qua_mario/mixin/PlayerEntityMixin.java b/mod/src/main/java/com/fqf/mario_qua_mario/mixin/PlayerEntityMixin.java index 7ca2490..d8ff590 100644 --- a/mod/src/main/java/com/fqf/mario_qua_mario/mixin/PlayerEntityMixin.java +++ b/mod/src/main/java/com/fqf/mario_qua_mario/mixin/PlayerEntityMixin.java @@ -2,15 +2,25 @@ import com.fqf.mario_qua_mario.mariodata.MarioMoveableData; import com.fqf.mario_qua_mario.mariodata.injections.MarioDataHolder; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; 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; @Mixin(PlayerEntity.class) -public abstract class PlayerEntityMixin implements MarioDataHolder { +public abstract class PlayerEntityMixin extends LivingEntity implements MarioDataHolder { + private PlayerEntityMixin(EntityType entityType, World world) { + super(entityType, world); + } + @Inject(method = "tick", at = @At("HEAD")) private void tickHook(CallbackInfo ci) { this.mqm$getMarioData().tick(); @@ -22,4 +32,20 @@ private void travelHook(Vec3d movementInput, CallbackInfo ci) { && moveableData.travelHook(movementInput.z, movementInput.x)) ci.cancel(); } + + @Override + protected boolean stepOnBlock(BlockPos pos, BlockState state, boolean playSound, boolean emitEvent, Vec3d movement) { + return switch (this.mqm$getMarioData().getAction().SLIDING_STATUS) { + case SLIDING, SLIDING_SILENT, SKIDDING -> false; + default -> super.stepOnBlock(pos, state, playSound, emitEvent, movement); + }; + } + + @Override + protected void playStepSounds(BlockPos pos, BlockState state) { + switch (this.mqm$getMarioData().getAction().SLIDING_STATUS) { + case SLIDING, SLIDING_SILENT, SKIDDING -> {} + default -> super.playStepSounds(pos, state); + }; + } } diff --git a/mod/src/main/resources/mario_qua_mario.accesswidener b/mod/src/main/resources/mario_qua_mario.accesswidener index 17a8512..0d325a8 100644 --- a/mod/src/main/resources/mario_qua_mario.accesswidener +++ b/mod/src/main/resources/mario_qua_mario.accesswidener @@ -1,3 +1,5 @@ accessWidener v2 named -accessible class net/minecraft/client/gui/hud/InGameHud$HeartType \ No newline at end of file +accessible class net/minecraft/client/gui/hud/InGameHud$HeartType +extendable method net/minecraft/entity/Entity stepOnBlock (Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;ZZLnet/minecraft/util/math/Vec3d;)Z +extendable method net/minecraft/entity/Entity playStepSounds (Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V \ No newline at end of file diff --git a/mod/src/main/resources/mario_qua_mario.mixins.json b/mod/src/main/resources/mario_qua_mario.mixins.json index bf7e6bd..fd87e60 100644 --- a/mod/src/main/resources/mario_qua_mario.mixins.json +++ b/mod/src/main/resources/mario_qua_mario.mixins.json @@ -3,7 +3,6 @@ "package": "com.fqf.mario_qua_mario.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "ExampleMixin", "PlayerEntityMarioDataMixin", "PlayerEntityMixin", "ServerPlayerMarioDataMixin"