Skip to content

Commit

Permalink
levitation totem work
Browse files Browse the repository at this point in the history
  • Loading branch information
MBatt1 committed Nov 13, 2024
1 parent be541ab commit 55dd601
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.id.paradiselost.client.rendering.util;

public class ParadiseLostEvents {

// world events
public static final int NITRA_EXPLODE = 2400;


// entity status events
public static final byte LEVITATION_TOTEM_USED = (byte) 2450;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
package net.id.paradiselost.entities.projectile;

import net.id.paradiselost.client.rendering.util.ParadiseLostWorldEvents;
import net.id.paradiselost.client.rendering.util.ParadiseLostEvents;
import net.id.paradiselost.entities.ParadiseLostEntityTypes;
import net.id.paradiselost.items.ParadiseLostItems;
import net.minecraft.component.type.PotionContentsComponent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityStatuses;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.projectile.thrown.ThrownItemEntity;
import net.minecraft.item.Item;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.potion.Potions;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.WorldEvents;

public class ThrownNitraEntity extends ThrownItemEntity {

Expand Down Expand Up @@ -47,7 +41,7 @@ protected void onCollision(HitResult hitResult) {

public void handleStatus(byte status) {
if (status == EntityStatuses.PLAY_DEATH_SOUND_OR_ADD_PROJECTILE_HIT_PARTICLES) {
this.getWorld().syncWorldEvent(ParadiseLostWorldEvents.NITRA_EXPLODE, this.getBlockPos(), 0);
this.getWorld().syncWorldEvent(ParadiseLostEvents.NITRA_EXPLODE, this.getBlockPos(), 0);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private static Settings unstackableRareTool() {

// misc
public static final SpyglassItem OLVITE_SPYGLASS = add("olvite_spyglass", new SpyglassItem(unstackableTool()));
public static final TotemOfLevitationItem TOTEM_OF_LEVITATION = add("totem_of_levitation", new TotemOfLevitationItem(new Item.Settings().maxCount(1).rarity(Rarity.UNCOMMON)));
public static final Item TOTEM_OF_LEVITATION = add("totem_of_levitation", new Item(new Item.Settings().maxCount(1).rarity(Rarity.UNCOMMON)));

// wands
public static final GravityWandItem LEVITA_WAND = add("levita_wand", new GravityWandItem(unstackableRareTool().maxDamage(100)));
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
package net.id.paradiselost.mixin.client.network;

import net.id.paradiselost.client.rendering.util.ParadiseLostEvents;
import net.id.paradiselost.client.sound.LevitaMovingMinecartSoundInstance;
import net.id.paradiselost.items.ParadiseLostItems;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import net.minecraft.client.network.ClientConnectionState;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.sound.GuardianAttackSoundInstance;
import net.minecraft.client.sound.SnifferDigSoundInstance;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.GuardianEntity;
import net.minecraft.entity.passive.SnifferEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundEvents;
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(ClientPlayNetworkHandler.class)
public abstract class ClientPlayNetworkHandlerMixin extends ClientCommonNetworkHandler {

@Shadow
private ClientWorld world;

public ClientPlayNetworkHandlerMixin(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) {
super(client, connection, connectionState);
}
Expand All @@ -26,4 +40,19 @@ private void playSpawnSound(Entity entity, CallbackInfo ci) {
this.client.getSoundManager().play(new LevitaMovingMinecartSoundInstance(abstractMinecartEntity, false));
}
}

@Inject(method = "onEntityStatus", at = @At("RETURN"))
public void onEntityStatus(EntityStatusS2CPacket packet, CallbackInfo ci) {
Entity entity = packet.getEntity(this.world);
if (entity != null) {
if (packet.getStatus() == ParadiseLostEvents.LEVITATION_TOTEM_USED) {
this.client.particleManager.addEmitter(entity, ParticleTypes.TOTEM_OF_UNDYING, 30);
this.world.playSound(entity.getX(), entity.getY(), entity.getZ(), SoundEvents.ITEM_TOTEM_USE, entity.getSoundCategory(), 1.0F, 1.0F, false);
if (entity == this.client.player) {
this.client.gameRenderer.showFloatingItem(ParadiseLostItems.TOTEM_OF_LEVITATION.getDefaultStack());
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package net.id.paradiselost.mixin.client.render;

import net.id.paradiselost.client.rendering.util.ParadiseLostWorldEvents;
import net.id.paradiselost.client.rendering.util.ParadiseLostEvents;
import net.id.paradiselost.items.ParadiseLostItems;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particle.ItemStackParticleEffect;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleTypes;
Expand All @@ -32,7 +31,7 @@ public abstract class WorldRendererMixin {
@Inject(method = "processWorldEvent(ILnet/minecraft/util/math/BlockPos;I)V", at = @At("TAIL"), cancellable = true)
public void processWorldEvent(int eventId, BlockPos pos, int data, CallbackInfo ci) {
Random random = this.world.random;
if (eventId == ParadiseLostWorldEvents.NITRA_EXPLODE) {
if (eventId == ParadiseLostEvents.NITRA_EXPLODE) {
this.world.playSoundAtBlockCenter(pos, SoundEvents.ENTITY_GENERIC_EXPLODE.value(), SoundCategory.NEUTRAL, 0.3F, 1.1F + random.nextFloat() * 0.4F, false);
for (int i = 0; i < 4; i++) {
this.addParticle(ParticleTypes.CLOUD,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
package net.id.paradiselost.mixin.entity;

import net.id.paradiselost.client.rendering.util.ParadiseLostEvents;
import net.id.paradiselost.entities.ParadiseLostEntityExtensions;
import net.id.paradiselost.entities.passive.moa.MoaAttributes;
import net.id.paradiselost.entities.passive.moa.MoaEntity;
import net.id.paradiselost.tag.ParadiseLostItemTags;
import net.id.paradiselost.util.MiscUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContextParameterSet;
import net.minecraft.loot.context.LootContextParameters;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeType;
import net.minecraft.recipe.SmeltingRecipe;
import net.minecraft.recipe.input.SingleStackRecipeInput;
import net.minecraft.registry.tag.DamageTypeTags;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArgs;
Expand All @@ -38,6 +47,19 @@ public LivingEntityMixin(EntityType<?> type, World world) {
super(type, world);
}

@Shadow
public abstract boolean isDead();

@Shadow
protected abstract float modifyAppliedDamage(DamageSource source, float amount);

@Shadow
@Final
public abstract boolean addStatusEffect(StatusEffectInstance effect);

@Shadow
public abstract float getHealth();

@Override
public boolean getFlipped() {
return flipped;
Expand Down Expand Up @@ -83,6 +105,38 @@ private void dropSmeltedLoot(Args args) {
}
}

@Inject(method = "damage", at = @At("HEAD"), cancellable = true)
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
if (!this.isInvulnerableTo(source) && !this.getWorld().isClient && !this.isDead()) {
if (source.isIn(DamageTypeTags.IS_FALL)) { // regular fall damage save
float modified = this.modifyAppliedDamage(source, amount);
System.out.println("TAKING: " + modified + " WITH HEALTH: " + getHealth());
// if damage 5 hearts or greater or player would be killed by the damage
if ((modified >= 10.0 || modified >= getHealth()) && MiscUtil.useLevitationTotem((LivingEntity) (Entity) this)) {
// apply effects
getWorld().sendEntityStatus(this, ParadiseLostEvents.LEVITATION_TOTEM_USED); // custom totem animation
setVelocity(this.getVelocity().x,0.6d, this.getVelocity().z);
velocityModified = true;
addStatusEffect(new StatusEffectInstance(StatusEffects.SLOW_FALLING, 15, 1));
// skip all other damage code
cir.setReturnValue(false);
}
} else if (source == getWorld().getDamageSources().outOfWorld()) { // void save
if (MiscUtil.useLevitationTotem((LivingEntity) (Entity) this)) {
// apply effects
getWorld().sendEntityStatus(this, ParadiseLostEvents.LEVITATION_TOTEM_USED); // custom totem animation
setVelocity(this.getVelocity().x,0.6d, this.getVelocity().z);
velocityModified = true;
addStatusEffect(new StatusEffectInstance(StatusEffects.LEVITATION, 110, 30));
addStatusEffect(new StatusEffectInstance(StatusEffects.SLOW_FALLING, 260, 1));
// skip all other damage code
cir.setReturnValue(false);
}
}
}
}

@Unique
@Nullable
private ItemEntity dropStackInternal(ItemStack stack) {
Optional<RecipeEntry<SmeltingRecipe>> optional = this.getWorld().getRecipeManager().getFirstMatch(RecipeType.SMELTING, new SingleStackRecipeInput(stack), getWorld());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package net.id.paradiselost.mixin.entity;

import net.id.paradiselost.client.rendering.util.ParadiseLostEvents;
import net.id.paradiselost.entities.ParadiseLostEntityExtensions;
import net.id.paradiselost.items.ParadiseLostItems;
import net.id.paradiselost.util.MiscUtil;
import net.id.paradiselost.util.ParadiseLostDamageTypes;
import net.id.paradiselost.world.dimension.ParadiseLostDimension;
import net.minecraft.entity.EntityType;
Expand All @@ -11,7 +13,6 @@
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Items;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.stat.Stats;
Expand Down Expand Up @@ -50,8 +51,16 @@ public PlayerEntityMixin(EntityType<? extends LivingEntity> type, World world) {
cancellable = true
)
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
if (source == getWorld().getDamageSources().outOfWorld() && getY() < getWorld().getBottomY() - 1 && getWorld().getRegistryKey() == ParadiseLostDimension.PARADISE_LOST_WORLD_KEY && !getWorld().getGameRules().getBoolean(PARADISE_VOID_KILLS)) {
if (!getWorld().isClient()) {

if (source == getWorld().getDamageSources().outOfWorld() && getWorld().getRegistryKey() == ParadiseLostDimension.PARADISE_LOST_WORLD_KEY && !getWorld().isClient()) {
if (MiscUtil.useLevitationTotem(this)) {
// apply effects
getWorld().sendEntityStatus(this, ParadiseLostEvents.LEVITATION_TOTEM_USED); // custom totem animation
setVelocity(this.getVelocity().x,0.6d, this.getVelocity().z);
velocityModified = true;
addStatusEffect(new StatusEffectInstance(StatusEffects.LEVITATION, 110, 50));
addStatusEffect(new StatusEffectInstance(StatusEffects.SLOW_FALLING, 260, 1));
} else if (!getWorld().getGameRules().getBoolean(PARADISE_VOID_KILLS) && getY() < getWorld().getBottomY() - 80) {
setParadiseLostFallen(true);
ServerWorld overworld = getServer().getWorld(World.OVERWORLD);
WorldBorder worldBorder = overworld.getWorldBorder();
Expand All @@ -67,7 +76,6 @@ public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boo
addStatusEffect(ef);
}
cir.setReturnValue(false);
cir.cancel();
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/main/java/net/id/paradiselost/util/MiscUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.JsonOps;
import net.id.paradiselost.items.ParadiseLostItems;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;

Expand Down Expand Up @@ -66,4 +70,19 @@ public static <T> T deserializeDataJson(DynamicOps<JsonElement> ops, Codec<T> co
}
}
}

public static boolean useLevitationTotem(LivingEntity entity) {
ItemStack itemStack = null;

for (Hand hand : Hand.values()) {
ItemStack itemStack2 = entity.getStackInHand(hand);
if (itemStack2.isOf(ParadiseLostItems.TOTEM_OF_LEVITATION)) {
itemStack = itemStack2.copy();
itemStack2.decrement(1);
break;
}
}

return itemStack != null;
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 55dd601

Please sign in to comment.