Skip to content

Commit

Permalink
Preparing to move most Entity Mixins into PlayerEntityMixin
Browse files Browse the repository at this point in the history
  • Loading branch information
floral-qua-floral committed Nov 30, 2024
1 parent 3c8e9f5 commit 0431012
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 111 deletions.
17 changes: 0 additions & 17 deletions api/src/main/java/com/floralquafloral/StompableEntity.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,25 +1,52 @@
package com.floralquafloral.mixin;

import com.floralquafloral.StompableEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.Saddleable;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.damage.DamageType;
import net.minecraft.entity.player.PlayerEntity;
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;
import net.minecraft.util.math.Vec3d;
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;
import org.spongepowered.asm.mixin.Unique;

@SuppressWarnings("UnusedMixin")
@Mixin(Entity.class)
public abstract class EntityStompabilityMixin implements StompableEntity {
@Shadow public abstract EntityType<?> getType();

@Override public StompResult qua_mario$stomp(Identifier stompType, DamageSource damageSource, float amount) {
// if(getType().isIn())
@Shadow public abstract boolean damage(DamageSource source, float amount);

return StompResult.NORMAL;
@Unique private static final TagKey<EntityType<?>> UNSTOMPABLE_ENTITIES =
TagKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of("qua_mario:unstompable"));
@Unique private static final TagKey<EntityType<?>> HURTS_TO_STOMP_ENTITIES =
TagKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of("qua_mario:hurts_to_stomp"));
@Unique private static final TagKey<EntityType<?>> IMMUNE_TO_BASIC_STOMP_ENTITIES =
TagKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of("qua_mario:immune_to_basic_stomp"));

@Unique private static final TagKey<DamageType> BASIC_STOMPS =
TagKey.of(RegistryKeys.DAMAGE_TYPE, Identifier.of("qua_mario:basic_stomps"));

@Override public StompResult qua_mario$stomp(PlayerEntity mario, Identifier stompType, DamageSource damageSource, float amount) {
Entity self = (Entity) (Object) this;

if(self instanceof VehicleEntity || (self instanceof Saddleable saddleable && saddleable.isSaddled()))
if((!(self instanceof MinecartEntity minecart) || minecart.getMinecartType() == AbstractMinecartEntity.Type.RIDEABLE))
if(mario.startRiding(self, false))
return StompResult.MOUNT;

if(getType().isIn(UNSTOMPABLE_ENTITIES)) return StompResult.FAIL;
if(getType().isIn(HURTS_TO_STOMP_ENTITIES)) return StompResult.PAINFUL;
if(getType().isIn(IMMUNE_TO_BASIC_STOMP_ENTITIES) && damageSource.isIn(BASIC_STOMPS)) return StompResult.FAIL;

boolean damaged = damage(damageSource, amount);
if(damaged) return StompResult.NORMAL;
else return StompResult.FAIL;
}
}
28 changes: 28 additions & 0 deletions api/src/main/java/com/floralquafloral/mixin/StompableEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.floralquafloral.mixin;

import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;

public interface StompableEntity {
StompResult qua_mario$stomp(PlayerEntity mario, Identifier stompType, DamageSource damageSource, float amount);

/**
* NORMAL - The Stomp behaves normally. Would be returned by a Goomba.
* PAINFUL - Trying to Stomp this entity hurts Mario. Would be returned by a Spiny or a Piranha Plant.
* GLANCING - Used internally. Returning this is not recommended.
* RESISTED - Mario bounces off this entity without hurting it. Would be returned by a Wiggler after the first time it's been stomped.
* FAIL_IF_BASIC - Mario passes through the entity unless he's Ground Pounding. Would be returned by a Blockhopper (look it up).
* FAIL - Mario can't stomp this entity. Would be returned by a Boo.
* MOUNT - Trying to Stomp this entity instead Mounts it. Would be returned by Yoshi.
*/
enum StompResult {
NORMAL,
PAINFUL,
GLANCING,
RESISTED,
FAIL_IF_BASIC,
FAIL,
MOUNT
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public MarioPlayerData(PlayerEntity mario) {
isEnabled()
&& !this.mario.getAbilities().flying
&& !this.mario.isFallFlying()
&& !this.mario.isUsingRiptide()
// && !mario.hasVehicle()
// && !mario.isClimbing()
);
Expand Down
148 changes: 68 additions & 80 deletions mod/src/main/java/com/floralquafloral/mixin/EntityMixin.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.floralquafloral.mixin;

import com.floralquafloral.MarioQuaMario;
import com.floralquafloral.StompableEntity;
import com.floralquafloral.mariodata.MarioDataManager;
import com.floralquafloral.mariodata.MarioPlayerData;
import com.floralquafloral.mariodata.moveable.MarioMainClientData;
Expand All @@ -13,13 +12,11 @@
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.block.BlockState;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
Expand Down Expand Up @@ -47,14 +44,6 @@

@Mixin(Entity.class)
public class EntityMixin {
@Inject(at = @At("HEAD"), method = "setSwimming(Z)V", cancellable = true)
private void setSwimming(boolean swimming, CallbackInfo ci) {
Entity entity = (Entity) (Object) this;
if(swimming && entity instanceof PlayerEntity player && MarioDataManager.getMarioData(player).isEnabled()) {
ci.cancel();
}
}

@Inject(at = @At("HEAD"), method = "isInSneakingPose", cancellable = true)
private void isInSneakingPose(CallbackInfoReturnable<Boolean> cir) {
if((Entity) (Object) this instanceof PlayerEntity player) {
Expand All @@ -66,7 +55,6 @@ private void isInSneakingPose(CallbackInfoReturnable<Boolean> cir) {
@Inject(method = "setPose", at = @At("HEAD"), cancellable = true)
private void preventSettingSneakPose(EntityPose pose, CallbackInfo ci) {
if((Entity) (Object) this instanceof PlayerEntity player && pose == EntityPose.CROUCHING) {
// MarioQuaMario.LOGGER.info("setPose called on player! Pose == {}", pose);
if(MarioDataManager.getMarioData(player).isSneakProhibited()) {

if(player.getPose() == EntityPose.CROUCHING)
Expand Down Expand Up @@ -136,74 +124,74 @@ private void executeStompsOnServer(MovementType movementType, Vec3d movement, Ca
}
}

@WrapOperation(method = "findCollisionsForMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getBlockCollisions(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/Box;)Ljava/lang/Iterable;"))
private static Iterable<VoxelShape> bumpBlocksOnCollision(World world, Entity entity, Box movingEntityBoundingBox, Operation<Iterable<VoxelShape>> original) {
// This doesn't work! Fix it!
if(false && entity instanceof ClientPlayerEntity) {
MarioMainClientData data = MarioMainClientData.getInstance();
if(data != null) {
Vec3d marioImmutableVelocity = data.getMario().getVelocity(); // is this adequate?
Vector3d marioVelocity = new Vector3d(marioImmutableVelocity.x, marioImmutableVelocity.y, marioImmutableVelocity.z);

boolean bumpCeilings = true || marioVelocity.y != 0 && data.getAction().BUMPING_RULE.CEILINGS != 0;
boolean bumpFloors = true || marioVelocity.y != 0 && data.getAction().BUMPING_RULE.FLOORS != 0;
boolean bumpWalls = true || (marioVelocity.x != 0 || marioVelocity.z != 0) && data.getAction().BUMPING_RULE.WALLS != 0;
Iterable<Pair<BlockPos, VoxelShape>> blockCollisions =
() -> new BlockCollisionSpliterator<>(world, entity, movingEntityBoundingBox, false, (pos, voxelShape) -> new Pair<>(pos, voxelShape));

EnumMap<Direction, Set<BlockPos>> bumpBlocks = new EnumMap<>(Direction.class);
for(Direction direction : Direction.values()) {
bumpBlocks.put(direction, new HashSet<>());
}

Box marioBoundingBox = entity.getBoundingBox();

for(Pair<BlockPos, VoxelShape> collidedBlock : blockCollisions) {
if((bumpCeilings || bumpFloors) && collidedBlock.getRight().calculateMaxDistance(Direction.Axis.Y, marioBoundingBox, marioVelocity.y) != 0) {
if(bumpCeilings && marioVelocity.y > 0) {
// Mario was moving up and bumped this block on the Y axis!
bumpBlocks.get(Direction.UP).add(collidedBlock.getLeft().toImmutable());
}
else if(bumpFloors && marioVelocity.y < 0) {
// Mario was moving down and bumped this block on the Y axis!
bumpBlocks.get(Direction.DOWN).add(collidedBlock.getLeft().toImmutable());
}
}
else if(bumpWalls) {
boolean xAxisFirst = Math.abs(marioVelocity.x) > Math.abs(marioVelocity.z);
if(xAxisFirst && collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x) != 0) {
MarioQuaMario.LOGGER.info("Collided along X axis: {}", collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x));
if(marioVelocity.x > 0)
bumpBlocks.get(Direction.EAST).add(collidedBlock.getLeft().toImmutable());
else
bumpBlocks.get(Direction.WEST).add(collidedBlock.getLeft().toImmutable());
}
else if(collidedBlock.getRight().calculateMaxDistance(Direction.Axis.Z, marioBoundingBox, marioVelocity.z) != 0) {
if(marioVelocity.z > 0)
bumpBlocks.get(Direction.SOUTH).add(collidedBlock.getLeft().toImmutable());
else
bumpBlocks.get(Direction.NORTH).add(collidedBlock.getLeft().toImmutable());
}
else if(!xAxisFirst && collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x) != 0) {
MarioQuaMario.LOGGER.info("Collided along X axis: {}", collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x));
if(marioVelocity.x > 0)
bumpBlocks.get(Direction.EAST).add(collidedBlock.getLeft().toImmutable());
else
bumpBlocks.get(Direction.WEST).add(collidedBlock.getLeft().toImmutable());
}
}
}

for(Direction direction : Direction.values()) {
Set<BlockPos> bumpBlocksInThisDirection = bumpBlocks.get(direction);
if(!bumpBlocksInThisDirection.isEmpty())
MarioQuaMario.LOGGER.info("BUMP {}:\t{}\t{}", direction.getName(), bumpBlocksInThisDirection.size(), bumpBlocksInThisDirection);
}
}
}

return original.call(world, entity, movingEntityBoundingBox);
}
// @WrapOperation(method = "findCollisionsForMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getBlockCollisions(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/Box;)Ljava/lang/Iterable;"))
// private static Iterable<VoxelShape> bumpBlocksOnCollision(World world, Entity entity, Box movingEntityBoundingBox, Operation<Iterable<VoxelShape>> original) {
// // This doesn't work! Fix it!
// if(false && entity instanceof ClientPlayerEntity) {
// MarioMainClientData data = MarioMainClientData.getInstance();
// if(data != null) {
// Vec3d marioImmutableVelocity = data.getMario().getVelocity(); // is this adequate?
// Vector3d marioVelocity = new Vector3d(marioImmutableVelocity.x, marioImmutableVelocity.y, marioImmutableVelocity.z);
//
// boolean bumpCeilings = true || marioVelocity.y != 0 && data.getAction().BUMPING_RULE.CEILINGS != 0;
// boolean bumpFloors = true || marioVelocity.y != 0 && data.getAction().BUMPING_RULE.FLOORS != 0;
// boolean bumpWalls = true || (marioVelocity.x != 0 || marioVelocity.z != 0) && data.getAction().BUMPING_RULE.WALLS != 0;
// Iterable<Pair<BlockPos, VoxelShape>> blockCollisions =
// () -> new BlockCollisionSpliterator<>(world, entity, movingEntityBoundingBox, false, (pos, voxelShape) -> new Pair<>(pos, voxelShape));
//
// EnumMap<Direction, Set<BlockPos>> bumpBlocks = new EnumMap<>(Direction.class);
// for(Direction direction : Direction.values()) {
// bumpBlocks.put(direction, new HashSet<>());
// }
//
// Box marioBoundingBox = entity.getBoundingBox();
//
// for(Pair<BlockPos, VoxelShape> collidedBlock : blockCollisions) {
// if((bumpCeilings || bumpFloors) && collidedBlock.getRight().calculateMaxDistance(Direction.Axis.Y, marioBoundingBox, marioVelocity.y) != 0) {
// if(bumpCeilings && marioVelocity.y > 0) {
// // Mario was moving up and bumped this block on the Y axis!
// bumpBlocks.get(Direction.UP).add(collidedBlock.getLeft().toImmutable());
// }
// else if(bumpFloors && marioVelocity.y < 0) {
// // Mario was moving down and bumped this block on the Y axis!
// bumpBlocks.get(Direction.DOWN).add(collidedBlock.getLeft().toImmutable());
// }
// }
// else if(bumpWalls) {
// boolean xAxisFirst = Math.abs(marioVelocity.x) > Math.abs(marioVelocity.z);
// if(xAxisFirst && collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x) != 0) {
// MarioQuaMario.LOGGER.info("Collided along X axis: {}", collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x));
// if(marioVelocity.x > 0)
// bumpBlocks.get(Direction.EAST).add(collidedBlock.getLeft().toImmutable());
// else
// bumpBlocks.get(Direction.WEST).add(collidedBlock.getLeft().toImmutable());
// }
// else if(collidedBlock.getRight().calculateMaxDistance(Direction.Axis.Z, marioBoundingBox, marioVelocity.z) != 0) {
// if(marioVelocity.z > 0)
// bumpBlocks.get(Direction.SOUTH).add(collidedBlock.getLeft().toImmutable());
// else
// bumpBlocks.get(Direction.NORTH).add(collidedBlock.getLeft().toImmutable());
// }
// else if(!xAxisFirst && collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x) != 0) {
// MarioQuaMario.LOGGER.info("Collided along X axis: {}", collidedBlock.getRight().calculateMaxDistance(Direction.Axis.X, marioBoundingBox, marioVelocity.x));
// if(marioVelocity.x > 0)
// bumpBlocks.get(Direction.EAST).add(collidedBlock.getLeft().toImmutable());
// else
// bumpBlocks.get(Direction.WEST).add(collidedBlock.getLeft().toImmutable());
// }
// }
// }
//
// for(Direction direction : Direction.values()) {
// Set<BlockPos> bumpBlocksInThisDirection = bumpBlocks.get(direction);
// if(!bumpBlocksInThisDirection.isEmpty())
// MarioQuaMario.LOGGER.info("BUMP {}:\t{}\t{}", direction.getName(), bumpBlocksInThisDirection.size(), bumpBlocksInThisDirection);
// }
// }
// }
//
// return original.call(world, entity, movingEntityBoundingBox);
// }

// @WrapOperation(method = "checkBlockCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;onEntityCollision(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;)V"))
// private void executeBumpsOnClient(BlockState instance, World world, BlockPos blockPos, Entity entity, Operation<Void> original) {
Expand Down
58 changes: 54 additions & 4 deletions mod/src/main/java/com/floralquafloral/mixin/PlayerEntityMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import com.floralquafloral.registries.states.character.ParsedCharacter;
import com.floralquafloral.registries.states.powerup.ParsedPowerUp;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.LivingEntity;
import net.minecraft.block.BlockState;
import net.minecraft.entity.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
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.Shadow;
import org.spongepowered.asm.mixin.injection.At;
Expand All @@ -19,11 +21,57 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin {
public abstract class PlayerEntityMixin extends LivingEntity {
private PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}

@Shadow public float strideDistance;

@Shadow public float prevStrideDistance;

@Override public void setSwimming(boolean swimming) {
if(swimming && MarioDataManager.getMarioData(this).isEnabled()) return;
super.setSwimming(swimming);
}

@Override
public boolean isInSneakingPose() {
return super.isInSneakingPose();
}

@Override
public void setPose(EntityPose pose) {
super.setPose(pose);
}

@Override
protected void playStepSound(BlockPos pos, BlockState state) {
super.playStepSound(pos, state);
}

@Override
public void move(MovementType movementType, Vec3d movement) {
super.move(movementType, movement);
}

@Override
public boolean startRiding(Entity entity, boolean force) {
boolean startedRiding = super.startRiding(entity, force);

return startedRiding;
}

@Override
public void readNbt(NbtCompound nbt) {
super.readNbt(nbt);
}

@Override
public NbtCompound writeNbt(NbtCompound nbt) {
return super.writeNbt(nbt);
}

@Inject(method = "travel", at = @At("HEAD"), cancellable = true)
private void travelHook(Vec3d movementInput, CallbackInfo ci) {
MarioPlayerData data = MarioDataManager.getMarioData(this);
Expand Down Expand Up @@ -102,4 +150,6 @@ public void changeDismounting(CallbackInfoReturnable<Boolean> cir) {
private boolean preventLivingEntityJump(LivingEntity instance) {
return !MarioDataManager.getMarioData(this).useMarioPhysics();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"values": [
"qua_mario:stomp",
"qua_mario:spin_jump"
]
}
Loading

0 comments on commit 0431012

Please sign in to comment.