mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-12 16:14:24 +01:00
Added sunglasses and broken sunglasses (credit @AtomicGlow for the idea)
This commit is contained in:
parent
81eff15912
commit
bea8272873
27 changed files with 342 additions and 18 deletions
|
@ -74,14 +74,14 @@ public class BatEeeeAbility implements Ability<Hit> {
|
||||||
Vec3d origin = player.getOriginVector();
|
Vec3d origin = player.getOriginVector();
|
||||||
|
|
||||||
if (rng.nextInt(20000) == 0) {
|
if (rng.nextInt(20000) == 0) {
|
||||||
player.getMaster().damage(MagicalDamageSource.create("eeee", player), 0.1F);
|
player.getMaster().damage(MagicalDamageSource.create("eeee", player).setBreakSunglasses(), 0.1F);
|
||||||
UCriteria.SCREECH_SELF.trigger(player.getMaster());
|
UCriteria.SCREECH_SELF.trigger(player.getMaster());
|
||||||
}
|
}
|
||||||
|
|
||||||
int total = player.findAllEntitiesInRange(5).mapToInt(e -> {
|
int total = player.findAllEntitiesInRange(5).mapToInt(e -> {
|
||||||
if (e instanceof LivingEntity && !SpellType.SHIELD.isOn(e)) {
|
if (e instanceof LivingEntity && !SpellType.SHIELD.isOn(e)) {
|
||||||
boolean isEarthPony = EquinePredicates.PLAYER_EARTH.test(e);
|
boolean isEarthPony = EquinePredicates.PLAYER_EARTH.test(e);
|
||||||
e.damage(MagicalDamageSource.create("eeee", player), isEarthPony ? 0.1F : 0.3F);
|
e.damage(MagicalDamageSource.create("eeee", player).setBreakSunglasses(), isEarthPony ? 0.1F : 0.3F);
|
||||||
|
|
||||||
Vec3d knockVec = origin.subtract(e.getPos());
|
Vec3d knockVec = origin.subtract(e.getPos());
|
||||||
((LivingEntity) e).takeKnockback(isEarthPony ? 0.3F : 0.5F, knockVec.getX(), knockVec.getZ());
|
((LivingEntity) e).takeKnockback(isEarthPony ? 0.3F : 0.5F, knockVec.getX(), knockVec.getZ());
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class RainboomAbilitySpell extends AbstractSpell {
|
||||||
}
|
}
|
||||||
|
|
||||||
source.findAllEntitiesInRange(rad).forEach(e -> {
|
source.findAllEntitiesInRange(rad).forEach(e -> {
|
||||||
e.damage(MagicalDamageSource.create("rainboom", source), 6);
|
e.damage(MagicalDamageSource.create("rainboom", source).setBreakSunglasses(), 6);
|
||||||
});
|
});
|
||||||
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range).forEach(pos -> {
|
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range).forEach(pos -> {
|
||||||
BlockState state = source.getReferenceWorld().getBlockState(pos);
|
BlockState state = source.getReferenceWorld().getBlockState(pos);
|
||||||
|
|
|
@ -65,6 +65,7 @@ public interface URenderers {
|
||||||
AccessoryFeatureRenderer.register(WingsFeatureRenderer::new);
|
AccessoryFeatureRenderer.register(WingsFeatureRenderer::new);
|
||||||
AccessoryFeatureRenderer.register(IcarusWingsFeatureRenderer::new);
|
AccessoryFeatureRenderer.register(IcarusWingsFeatureRenderer::new);
|
||||||
AccessoryFeatureRenderer.register(BatWingsFeatureRenderer::new);
|
AccessoryFeatureRenderer.register(BatWingsFeatureRenderer::new);
|
||||||
|
AccessoryFeatureRenderer.register(GlassesFeatureRenderer::new);
|
||||||
|
|
||||||
EntityRendererRegistry.register(UEntities.THROWN_ITEM, FlyingItemEntityRenderer::new);
|
EntityRendererRegistry.register(UEntities.THROWN_ITEM, FlyingItemEntityRenderer::new);
|
||||||
EntityRendererRegistry.register(UEntities.MUFFIN, FlyingItemEntityRenderer::new);
|
EntityRendererRegistry.register(UEntities.MUFFIN, FlyingItemEntityRenderer::new);
|
||||||
|
|
|
@ -13,11 +13,13 @@ import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.client.KeyBindingsHandler;
|
import com.minelittlepony.unicopia.client.KeyBindingsHandler;
|
||||||
import com.minelittlepony.unicopia.client.sound.LoopingSoundInstance;
|
import com.minelittlepony.unicopia.client.sound.*;
|
||||||
import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance;
|
import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance;
|
||||||
import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect;
|
import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect;
|
||||||
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
import com.minelittlepony.unicopia.item.GlassesItem;
|
||||||
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
@ -28,10 +30,10 @@ import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.EntityDimensions;
|
import net.minecraft.entity.EntityDimensions;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Quaternion;
|
import net.minecraft.util.math.Quaternion;
|
||||||
import net.minecraft.util.math.Vec3f;
|
import net.minecraft.util.math.Vec3f;
|
||||||
|
@ -65,6 +67,8 @@ public class UHud extends DrawableHelper {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private LoopingSoundInstance<PlayerEntity> heartbeatSound;
|
private LoopingSoundInstance<PlayerEntity> heartbeatSound;
|
||||||
|
@Nullable
|
||||||
|
private LoopingSoundInstance<PlayerEntity> partySound;
|
||||||
|
|
||||||
public void render(InGameHud hud, MatrixStack matrices, float tickDelta) {
|
public void render(InGameHud hud, MatrixStack matrices, float tickDelta) {
|
||||||
|
|
||||||
|
@ -210,7 +214,10 @@ public class UHud extends DrawableHelper {
|
||||||
|
|
||||||
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
||||||
|
|
||||||
if (hasEffect || (pony.getSpecies() == Race.BAT && SunBlindnessStatusEffect.hasSunExposure(client.player))) {
|
ItemStack glasses = GlassesItem.getForEntity(client.player);
|
||||||
|
boolean hasSunglasses = glasses.getItem() == UItems.SUNGLASSES;
|
||||||
|
|
||||||
|
if (hasEffect || (!hasSunglasses && pony.getSpecies() == Race.BAT && SunBlindnessStatusEffect.hasSunExposure(client.player))) {
|
||||||
float i = hasEffect ? (client.player.getStatusEffect(UEffects.SUN_BLINDNESS).getDuration() - tickDelta) / SunBlindnessStatusEffect.MAX_DURATION : 0;
|
float i = hasEffect ? (client.player.getStatusEffect(UEffects.SUN_BLINDNESS).getDuration() - tickDelta) / SunBlindnessStatusEffect.MAX_DURATION : 0;
|
||||||
|
|
||||||
float pulse = (1 + (float)Math.sin(client.player.age / 108F)) * 0.25F;
|
float pulse = (1 + (float)Math.sin(client.player.age / 108F)) * 0.25F;
|
||||||
|
@ -235,13 +242,42 @@ public class UHud extends DrawableHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasSunglasses) {
|
||||||
|
|
||||||
|
if (glasses.hasCustomName() && "Cool Shades".equals(glasses.getName().getString())) {
|
||||||
|
final int delay = 7;
|
||||||
|
final int current = client.player.age / delay;
|
||||||
|
final int tint = DyeColor.byId(current % DyeColor.values().length).getSignColor();
|
||||||
|
fillGradient(matrices, 0, 0, scaledWidth, scaledHeight, 0x1F000000 | tint, 0x5F000000 | tint);
|
||||||
|
|
||||||
|
if (partySound == null || partySound.isDone()) {
|
||||||
|
client.getSoundManager().play(
|
||||||
|
partySound = new LoopingSoundInstance<>(client.player, player -> {
|
||||||
|
return UItems.SUNGLASSES.isApplicable(player) || true;
|
||||||
|
}, SoundEvents.MUSIC_DISC_PIGSTEP, 1, 1, client.world.random)
|
||||||
|
);
|
||||||
|
} else if (partySound != null) {
|
||||||
|
partySound.setMuted(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (partySound != null) {
|
||||||
|
partySound.setMuted(true);
|
||||||
|
}
|
||||||
|
fillGradient(matrices, 0, 0, scaledWidth, scaledHeight, 0x0F000088, 0xAF000000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (partySound != null) {
|
||||||
|
partySound.setMuted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float exhaustion = pony.getMagicalReserves().getExhaustion().getPercentFill();
|
float exhaustion = pony.getMagicalReserves().getExhaustion().getPercentFill();
|
||||||
|
|
||||||
if (exhaustion > 0) {
|
if (exhaustion > 0) {
|
||||||
if (exhaustion > 0.5F && (heartbeatSound == null || heartbeatSound.isDone())) {
|
if (exhaustion > 0.5F && (heartbeatSound == null || heartbeatSound.isDone())) {
|
||||||
client.getSoundManager().play(
|
client.getSoundManager().play(
|
||||||
heartbeatSound = new LoopingSoundInstance<>(client.player, player -> {
|
heartbeatSound = new LoopingSoundInstance<>(client.player, player -> {
|
||||||
return Pony.of(player).getMagicalReserves().getExhaustion().getPercentFill() > 0.5F;
|
return partySound != null && Pony.of(player).getMagicalReserves().getExhaustion().getPercentFill() > 0.5F;
|
||||||
}, USounds.ENTITY_PLAYER_HEARTBEAT, 1, 1, client.world.random)
|
}, USounds.ENTITY_PLAYER_HEARTBEAT, 1, 1, client.world.random)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.minelittlepony.unicopia.client.minelittlepony;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.model.BodyPart;
|
||||||
|
import com.minelittlepony.api.model.IModel;
|
||||||
|
import com.minelittlepony.api.model.gear.IGear;
|
||||||
|
import com.minelittlepony.unicopia.client.render.GlassesFeatureRenderer.GlassesModel;
|
||||||
|
import com.minelittlepony.unicopia.item.GlassesItem;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.*;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
|
class GlassesGear extends GlassesModel implements IGear {
|
||||||
|
|
||||||
|
private final Map<Identifier, Identifier> textures = new HashMap<>();
|
||||||
|
|
||||||
|
public GlassesGear() {
|
||||||
|
super(GlassesModel.getData(new Dilation(0.3F), -6, -6).createModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRender(IModel model, Entity entity) {
|
||||||
|
return entity instanceof LivingEntity living && !GlassesItem.getForEntity(living).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BodyPart getGearLocation() {
|
||||||
|
return BodyPart.HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
|
||||||
|
return textures.computeIfAbsent(Registry.ITEM.getId(GlassesItem.getForEntity((LivingEntity)entity).getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack stack, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha, UUID interpolatorId) {
|
||||||
|
render(stack, consumer, light, overlay, red, green, blue, 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
|
||||||
IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND));
|
IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND));
|
||||||
IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND));
|
IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND));
|
||||||
IGear.register(AmuletGear::new);
|
IGear.register(AmuletGear::new);
|
||||||
|
IGear.register(GlassesGear::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.GlassesItem;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.*;
|
||||||
|
import net.minecraft.client.render.OverlayTexture;
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||||
|
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
|
import net.minecraft.client.render.entity.model.EntityModelPartNames;
|
||||||
|
import net.minecraft.client.render.item.ItemRenderer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
|
public class GlassesFeatureRenderer<E extends LivingEntity> implements AccessoryFeatureRenderer.Feature<E> {
|
||||||
|
|
||||||
|
private final GlassesModel model;
|
||||||
|
|
||||||
|
private final Map<Identifier, Identifier> textures = new HashMap<>();
|
||||||
|
|
||||||
|
private final FeatureRendererContext<E, ? extends BipedEntityModel<E>> context;
|
||||||
|
|
||||||
|
public GlassesFeatureRenderer(FeatureRendererContext<E, ? extends BipedEntityModel<E>> context) {
|
||||||
|
this.context = context;
|
||||||
|
this.model = new GlassesModel(GlassesModel.getData(Dilation.NONE, -8, -4).createModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch) {
|
||||||
|
|
||||||
|
ItemStack stack = GlassesItem.getForEntity(entity);
|
||||||
|
|
||||||
|
if (!stack.isEmpty()) {
|
||||||
|
Identifier texture = textures.computeIfAbsent(Registry.ITEM.getId(stack.getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||||
|
|
||||||
|
VertexConsumer consumer = ItemRenderer.getArmorGlintConsumer(renderContext, RenderLayer.getArmorCutoutNoCull(texture), false, false);
|
||||||
|
|
||||||
|
model.setAngles(entity, context.getModel());
|
||||||
|
model.render(matrices, consumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GlassesModel extends Model {
|
||||||
|
|
||||||
|
private final ModelPart root;
|
||||||
|
|
||||||
|
public GlassesModel(ModelPart tree) {
|
||||||
|
super(RenderLayer::getEntityTranslucent);
|
||||||
|
root = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TexturedModelData getData(Dilation dilation, int y, int z) {
|
||||||
|
ModelData data = new ModelData();
|
||||||
|
ModelPartData root = data.getRoot();
|
||||||
|
|
||||||
|
root.addChild(EntityModelPartNames.HEAD, ModelPartBuilder.create().uv(0, 0).cuboid(-4, y, z, 8, 8, 8, dilation.add(0.2F)), ModelTransform.NONE);
|
||||||
|
root.addChild(EntityModelPartNames.HAT, ModelPartBuilder.create().uv(32, 0).cuboid(-4, y, z, 8, 8, 8, dilation.add(0.4F)), ModelTransform.NONE);
|
||||||
|
|
||||||
|
return TexturedModelData.of(data, 64, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngles(LivingEntity entity, BipedEntityModel<?> biped) {
|
||||||
|
root.getChild(EntityModelPartNames.HEAD).copyTransform(biped.head);
|
||||||
|
root.getChild(EntityModelPartNames.HAT).copyTransform(biped.hat);
|
||||||
|
|
||||||
|
root.getChild(EntityModelPartNames.HAT).resetTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int i, int j, float f, float g, float h, float k) {
|
||||||
|
root.render(matrices, vertexConsumer, i, j, f, g, h, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ public abstract class FadeOutSoundInstance extends MovingSoundInstance {
|
||||||
private int progress;
|
private int progress;
|
||||||
|
|
||||||
private boolean fadingOut;
|
private boolean fadingOut;
|
||||||
|
private boolean muted;
|
||||||
|
private int ticksMuted;
|
||||||
|
|
||||||
public FadeOutSoundInstance(SoundEvent sound, SoundCategory category, float volume, Random random) {
|
public FadeOutSoundInstance(SoundEvent sound, SoundCategory category, float volume, Random random) {
|
||||||
super(sound, category, random);
|
super(sound, category, random);
|
||||||
|
@ -33,9 +35,24 @@ public abstract class FadeOutSoundInstance extends MovingSoundInstance {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMuted(boolean muted) {
|
||||||
|
this.muted = muted;
|
||||||
|
this.repeat = !muted;
|
||||||
|
if (!muted) {
|
||||||
|
ticksMuted = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void tick() {
|
public final void tick() {
|
||||||
setFadingOut(!shouldKeepPlaying());
|
boolean fadeOut = !shouldKeepPlaying();
|
||||||
|
|
||||||
|
if (!muted) {
|
||||||
|
setFadingOut(fadeOut);
|
||||||
|
} else if (ticksMuted++ > 2000) {
|
||||||
|
setDone();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
prevProgress = progress;
|
prevProgress = progress;
|
||||||
if (progress < transitionTicks) {
|
if (progress < transitionTicks) {
|
||||||
|
@ -72,6 +89,9 @@ public abstract class FadeOutSoundInstance extends MovingSoundInstance {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final float getVolume() {
|
public final float getVolume() {
|
||||||
|
if (muted) {
|
||||||
|
return 0.001F;
|
||||||
|
}
|
||||||
return getLerpedVolume() * sound.getVolume().get(field_38800);
|
return getLerpedVolume() * sound.getVolume().get(field_38800);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,12 @@ import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
||||||
import com.minelittlepony.unicopia.block.data.DragonBreathStore;
|
import com.minelittlepony.unicopia.block.data.DragonBreathStore;
|
||||||
|
import com.minelittlepony.unicopia.item.GlassesItem;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
import com.minelittlepony.unicopia.network.datasync.EffectSync;
|
import com.minelittlepony.unicopia.network.datasync.EffectSync;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
|
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
|
||||||
|
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
||||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
|
@ -28,6 +30,7 @@ import net.minecraft.entity.projectile.ProjectileEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -168,11 +171,21 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source instanceof MagicalDamageSource) {
|
if (source instanceof MagicalDamageSource magical) {
|
||||||
Entity attacker = ((MagicalDamageSource)source).getSpell();
|
Entity attacker = ((MagicalDamageSource)source).getSpell();
|
||||||
if (attacker != null) {
|
if (attacker != null) {
|
||||||
this.attacker = attacker;
|
this.attacker = attacker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (magical.breaksSunglasses()) {
|
||||||
|
ItemStack glasses = GlassesItem.getForEntity(entity);
|
||||||
|
if (glasses.getItem() == UItems.SUNGLASSES) {
|
||||||
|
ItemStack broken = UItems.BROKEN_SUNGLASSES.getDefaultStack();
|
||||||
|
broken.setNbt(glasses.getNbt());
|
||||||
|
TrinketsDelegate.getInstance().setEquippedStack(entity, TrinketsDelegate.FACE, broken);
|
||||||
|
entity.world.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_GLASS_BREAK, SoundCategory.PLAYERS, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.UTags;
|
import com.minelittlepony.unicopia.UTags;
|
||||||
|
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
@ -63,10 +64,15 @@ public class SunBlindnessStatusEffect extends StatusEffect {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.SHADES)) {
|
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.SHADES)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TrinketsDelegate.getInstance().getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.SHADES))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (entity.world.isClient) {
|
if (entity.world.isClient) {
|
||||||
entity.world.calculateAmbientDarkness();
|
entity.world.calculateAmbientDarkness();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.minelittlepony.unicopia.item;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.item.ArmorMaterials;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.sound.SoundEvent;
|
||||||
|
|
||||||
|
public class GlassesItem extends WearableItem {
|
||||||
|
public GlassesItem(FabricItemSettings settings) {
|
||||||
|
super(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoundEvent getEquipSound() {
|
||||||
|
return ArmorMaterials.LEATHER.getEquipSound();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EquipmentSlot getPreferredSlot(ItemStack stack) {
|
||||||
|
return EquipmentSlot.HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApplicable(LivingEntity entity) {
|
||||||
|
return getForEntity(entity).getItem() == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack getForEntity(LivingEntity entity) {
|
||||||
|
return TrinketsDelegate.getInstance().getEquipped(entity, TrinketsDelegate.FACE)
|
||||||
|
.filter(stack -> stack.getItem() instanceof GlassesItem)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,6 +116,9 @@ public interface UItems {
|
||||||
.rarity(Rarity.RARE)
|
.rarity(Rarity.RARE)
|
||||||
.group(ItemGroup.DECORATIONS)));
|
.group(ItemGroup.DECORATIONS)));
|
||||||
|
|
||||||
|
GlassesItem SUNGLASSES = register("sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1).group(ItemGroup.COMBAT)));
|
||||||
|
GlassesItem BROKEN_SUNGLASSES = register("broken_sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1).group(ItemGroup.COMBAT)));
|
||||||
|
|
||||||
static <T extends Item> T register(String name, T item) {
|
static <T extends Item> T register(String name, T item) {
|
||||||
return register(Unicopia.id(name), item);
|
return register(Unicopia.id(name), item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,8 @@ public abstract class WearableItem extends Item implements Wearable {
|
||||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
return TrinketsDelegate.getInstance().getAvailableTrinketSlots(player, TrinketsDelegate.ALL).stream()
|
return TrinketsDelegate.getInstance().getAvailableTrinketSlots(player, TrinketsDelegate.ALL).stream()
|
||||||
.findAny()
|
|
||||||
.filter(slotId -> TrinketsDelegate.getInstance().equipStack(player, slotId, stack))
|
.filter(slotId -> TrinketsDelegate.getInstance().equipStack(player, slotId, stack))
|
||||||
|
.findAny()
|
||||||
.map(slotId -> TypedActionResult.success(stack, world.isClient()))
|
.map(slotId -> TypedActionResult.success(stack, world.isClient()))
|
||||||
.orElseGet(() -> TypedActionResult.fail(stack));
|
.orElseGet(() -> TypedActionResult.fail(stack));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,9 @@ public interface TrinketsDelegate {
|
||||||
Identifier MAINHAND = new Identifier("hand:glove");
|
Identifier MAINHAND = new Identifier("hand:glove");
|
||||||
Identifier OFFHAND = new Identifier("offhand:glove");
|
Identifier OFFHAND = new Identifier("offhand:glove");
|
||||||
Identifier NECKLACE = new Identifier("chest:necklace");
|
Identifier NECKLACE = new Identifier("chest:necklace");
|
||||||
|
Identifier FACE = new Identifier("head:face");
|
||||||
|
|
||||||
Set<Identifier> ALL = new TreeSet<>(List.of(MAINHAND, OFFHAND, NECKLACE));
|
Set<Identifier> ALL = new TreeSet<>(List.of(MAINHAND, OFFHAND, NECKLACE, FACE));
|
||||||
|
|
||||||
TrinketsDelegate EMPTY = new TrinketsDelegate() {};
|
TrinketsDelegate EMPTY = new TrinketsDelegate() {};
|
||||||
|
|
||||||
|
@ -48,12 +49,26 @@ public interface TrinketsDelegate {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void setEquippedStack(LivingEntity entity, Identifier slot, ItemStack stack) {
|
||||||
|
EquipmentSlot eq = slot == FACE ? EquipmentSlot.HEAD
|
||||||
|
: slot == NECKLACE ? EquipmentSlot.CHEST
|
||||||
|
: slot == MAINHAND ? EquipmentSlot.CHEST
|
||||||
|
: slot == OFFHAND ? EquipmentSlot.OFFHAND
|
||||||
|
: null;
|
||||||
|
if (eq != null) {
|
||||||
|
entity.equipStack(eq, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default Set<Identifier> getAvailableTrinketSlots(LivingEntity entity, Set<Identifier> probedSlots) {
|
default Set<Identifier> getAvailableTrinketSlots(LivingEntity entity, Set<Identifier> probedSlots) {
|
||||||
return probedSlots.stream().filter(slot -> getEquipped(entity, slot).count() == 0).collect(Collectors.toSet());
|
return probedSlots.stream().filter(slot -> getEquipped(entity, slot).count() == 0).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
default Stream<ItemStack> getEquipped(LivingEntity entity, Identifier slot) {
|
default Stream<ItemStack> getEquipped(LivingEntity entity, Identifier slot) {
|
||||||
|
|
||||||
|
if (slot == FACE) {
|
||||||
|
return Stream.of(entity.getEquippedStack(EquipmentSlot.HEAD));
|
||||||
|
}
|
||||||
if (slot == NECKLACE || slot == MAINHAND) {
|
if (slot == NECKLACE || slot == MAINHAND) {
|
||||||
return Stream.of(entity.getEquippedStack(EquipmentSlot.CHEST));
|
return Stream.of(entity.getEquippedStack(EquipmentSlot.CHEST));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,19 @@ public class TrinketsDelegateImpl implements TrinketsDelegate {
|
||||||
}).orElse(false);
|
}).orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEquippedStack(LivingEntity entity, Identifier slot, ItemStack stack) {
|
||||||
|
getInventory(entity, slot).ifPresent(inventory -> {
|
||||||
|
SoundEvent soundEvent = stack.getEquipSound();
|
||||||
|
inventory.clear();
|
||||||
|
inventory.setStack(0, stack);
|
||||||
|
if (soundEvent != null) {
|
||||||
|
entity.emitGameEvent(GameEvent.EQUIP);
|
||||||
|
entity.playSound(soundEvent, 1, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Identifier> getAvailableTrinketSlots(LivingEntity entity, Set<Identifier> probedSlots) {
|
public Set<Identifier> getAvailableTrinketSlots(LivingEntity entity, Set<Identifier> probedSlots) {
|
||||||
probedSlots = new HashSet<>(probedSlots);
|
probedSlots = new HashSet<>(probedSlots);
|
||||||
|
|
|
@ -27,20 +27,22 @@ public class MagicalDamageSource extends EntityDamageSource {
|
||||||
return new DamageSource(type) {};
|
return new DamageSource(type) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DamageSource create(String type) {
|
public static MagicalDamageSource create(String type) {
|
||||||
return new MagicalDamageSource(type, null, null, false, false);
|
return new MagicalDamageSource(type, null, null, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DamageSource create(String type, @Nullable LivingEntity source) {
|
public static MagicalDamageSource create(String type, @Nullable LivingEntity source) {
|
||||||
return new MagicalDamageSource(type, source, null, false, false);
|
return new MagicalDamageSource(type, source, null, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DamageSource create(String type, Caster<?> caster) {
|
public static MagicalDamageSource create(String type, Caster<?> caster) {
|
||||||
return new MagicalDamageSource(type, caster.getMaster(), caster.getEntity(), false, false);
|
return new MagicalDamageSource(type, caster.getMaster(), caster.getEntity(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entity spell;
|
private Entity spell;
|
||||||
|
|
||||||
|
private boolean breakSunglasses;
|
||||||
|
|
||||||
protected MagicalDamageSource(String type, @Nullable Entity spell, boolean direct, boolean unblockable) {
|
protected MagicalDamageSource(String type, @Nullable Entity spell, boolean direct, boolean unblockable) {
|
||||||
this(type, null, spell, direct, unblockable);
|
this(type, null, spell, direct, unblockable);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +59,15 @@ public class MagicalDamageSource extends EntityDamageSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MagicalDamageSource setBreakSunglasses() {
|
||||||
|
breakSunglasses = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean breaksSunglasses() {
|
||||||
|
return breakSunglasses;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Entity getSpell() {
|
public Entity getSpell() {
|
||||||
return spell;
|
return spell;
|
||||||
|
|
|
@ -53,6 +53,9 @@
|
||||||
"item.unicopia.juice": "Juice",
|
"item.unicopia.juice": "Juice",
|
||||||
"item.unicopia.burned_juice": "Burned Juice",
|
"item.unicopia.burned_juice": "Burned Juice",
|
||||||
|
|
||||||
|
"item.unicopia.sunglasses": "Sunglasses",
|
||||||
|
"item.unicopia.broken_sunglasses": "Broken Sunglasses",
|
||||||
|
|
||||||
"item.unicopia.pebbles": "Pebbles",
|
"item.unicopia.pebbles": "Pebbles",
|
||||||
"item.unicopia.rock": "Rock",
|
"item.unicopia.rock": "Rock",
|
||||||
"item.unicopia.weird_rock": "Weird Rock",
|
"item.unicopia.weird_rock": "Weird Rock",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/broken_sunglasses"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/sunglasses"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 928 B |
BIN
src/main/resources/assets/unicopia/textures/item/sunglasses.png
Normal file
BIN
src/main/resources/assets/unicopia/textures/item/sunglasses.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
|
@ -5,6 +5,7 @@
|
||||||
"slots": [
|
"slots": [
|
||||||
"hand/glove",
|
"hand/glove",
|
||||||
"offhand/glove",
|
"offhand/glove",
|
||||||
"chest/necklace"
|
"chest/necklace",
|
||||||
|
"head/face"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"unicopia:sunglasses",
|
||||||
|
"unicopia:broken_sunglasses"
|
||||||
|
]
|
||||||
|
}
|
14
src/main/resources/data/unicopia/recipes/sunglasses.json
Normal file
14
src/main/resources/data/unicopia/recipes/sunglasses.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"pattern": [
|
||||||
|
"**"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"*": {
|
||||||
|
"item": "minecraft:glass"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "unicopia:sunglasses"
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
"minecraft:player_head",
|
"minecraft:player_head",
|
||||||
"minecraft:zombie_head",
|
"minecraft:zombie_head",
|
||||||
"minecraft:creeper_head",
|
"minecraft:creeper_head",
|
||||||
"minecraft:dragon_head"
|
"minecraft:dragon_head",
|
||||||
|
"unicopia:sunglasses"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue