mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 13:37:58 +01:00
The pearl necklace now has 4 durability
This commit is contained in:
parent
e2f2b83003
commit
498ec2bca0
28 changed files with 194 additions and 86 deletions
|
@ -10,8 +10,10 @@ import com.minelittlepony.unicopia.Race;
|
|||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
|
@ -73,6 +75,11 @@ public class ChangeFormAbility implements Ability<Hit> {
|
|||
|
||||
List<Pony> targets = getTargets(player).toList();
|
||||
player.subtractEnergyCost(5 * targets.size());
|
||||
TrinketsDelegate.EquippedStack amulet = UItems.PEARL_NECKLACE.getForEntity(player.asEntity());
|
||||
if (!amulet.stack().isEmpty()) {
|
||||
amulet.stack().damage(1, player.asEntity(), amulet.breakStatusSender());
|
||||
}
|
||||
|
||||
boolean isTransforming = player.getSuppressedRace().isUnset();
|
||||
targets.forEach(target -> {
|
||||
Race supressed = target.getSuppressedRace();
|
||||
|
|
|
@ -214,8 +214,8 @@ public class UHud {
|
|||
|
||||
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
||||
|
||||
ItemStack glasses = GlassesItem.getForEntity(client.player);
|
||||
boolean hasSunglasses = glasses.getItem() == UItems.SUNGLASSES;
|
||||
ItemStack glasses = GlassesItem.getForEntity(client.player).stack();
|
||||
boolean hasSunglasses = glasses.isOf(UItems.SUNGLASSES);
|
||||
|
||||
if (hasEffect || (!hasSunglasses && pony.getObservedSpecies() == Race.BAT && SunBlindnessStatusEffect.hasSunExposure(client.player))) {
|
||||
float i = hasEffect ? (client.player.getStatusEffect(UEffects.SUN_BLINDNESS).getDuration() - tickDelta) / SunBlindnessStatusEffect.MAX_DURATION : 0;
|
||||
|
|
|
@ -31,7 +31,7 @@ class AmuletGear extends AmuletModel implements IGear {
|
|||
|
||||
@Override
|
||||
public boolean canRender(IModel model, Entity entity) {
|
||||
return entity instanceof LivingEntity living && !AmuletItem.getForEntity(living).isEmpty();
|
||||
return entity instanceof LivingEntity living && !AmuletItem.get(living).stack().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +41,7 @@ class AmuletGear extends AmuletModel implements IGear {
|
|||
|
||||
@Override
|
||||
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
|
||||
return textures.computeIfAbsent(Registries.ITEM.getId(AmuletItem.getForEntity((LivingEntity)entity).getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||
return textures.computeIfAbsent(Registries.ITEM.getId(AmuletItem.get((LivingEntity)entity).stack().getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -67,8 +67,8 @@ class BangleGear implements IGear {
|
|||
public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
|
||||
alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getModel().startsWith("slim");
|
||||
FriendshipBraceletItem.getWornBangles((LivingEntity)entity, slot).findFirst().ifPresent(bracelet -> {
|
||||
color = ((DyeableItem)bracelet.getItem()).getColor(bracelet);
|
||||
glowing = ((GlowableItem)bracelet.getItem()).isGlowing(bracelet);
|
||||
color = ((DyeableItem)bracelet.stack().getItem()).getColor(bracelet.stack());
|
||||
glowing = ((GlowableItem)bracelet.stack().getItem()).isGlowing(bracelet.stack());
|
||||
});
|
||||
BraceletModel m = alex ? alexModel : steveModel;
|
||||
|
||||
|
@ -76,7 +76,7 @@ class BangleGear implements IGear {
|
|||
m.setAngles(biped);
|
||||
}
|
||||
Arm mainArm = ((LivingEntity)entity).getMainArm();
|
||||
m.setVisible(slot == TrinketsDelegate.MAINHAND ? mainArm : mainArm.getOpposite());
|
||||
m.setVisible(slot == TrinketsDelegate.MAIN_GLOVE ? mainArm : mainArm.getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,7 +28,7 @@ class GlassesGear extends GlassesModel implements IGear {
|
|||
|
||||
@Override
|
||||
public boolean canRender(IModel model, Entity entity) {
|
||||
return entity instanceof LivingEntity living && !GlassesItem.getForEntity(living).isEmpty();
|
||||
return entity instanceof LivingEntity living && !GlassesItem.getForEntity(living).stack().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,7 +38,7 @@ class GlassesGear extends GlassesModel implements IGear {
|
|||
|
||||
@Override
|
||||
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
|
||||
return textures.computeIfAbsent(Registries.ITEM.getId(GlassesItem.getForEntity((LivingEntity)entity).getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||
return textures.computeIfAbsent(Registries.ITEM.getId(GlassesItem.getForEntity((LivingEntity)entity).stack().getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,8 +44,8 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
|
|||
public void onInitializeClient() {
|
||||
INSTANCE = this;
|
||||
PonyModelPrepareCallback.EVENT.register(this::onPonyModelPrepared);
|
||||
IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND));
|
||||
IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND));
|
||||
IGear.register(() -> new BangleGear(TrinketsDelegate.MAIN_GLOVE));
|
||||
IGear.register(() -> new BangleGear(TrinketsDelegate.SECONDARY_GLOVE));
|
||||
IGear.register(HeldEntityGear::new);
|
||||
IGear.register(BodyPartGear::pegasusWings);
|
||||
IGear.register(BodyPartGear::batWings);
|
||||
|
|
|
@ -42,7 +42,7 @@ public class AmuletFeatureRenderer<E extends LivingEntity> implements AccessoryF
|
|||
@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 = AmuletItem.getForEntity(entity);
|
||||
ItemStack stack = AmuletItem.get(entity).stack();
|
||||
|
||||
if (!stack.isEmpty()) {
|
||||
Identifier texture = textures.computeIfAbsent(Registries.ITEM.getId(stack.getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||
|
|
|
@ -48,11 +48,11 @@ public class BraceletFeatureRenderer<E extends LivingEntity> implements Accessor
|
|||
|
||||
@Override
|
||||
public void render(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch) {
|
||||
FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.MAINHAND).findFirst().ifPresent(bangle -> {
|
||||
renderBangleThirdPerson(bangle, stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm());
|
||||
FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.MAIN_GLOVE).findFirst().ifPresent(bangle -> {
|
||||
renderBangleThirdPerson(bangle.stack(), stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm());
|
||||
});
|
||||
FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.OFFHAND).findFirst().ifPresent(bangle -> {
|
||||
renderBangleThirdPerson(bangle, stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm().getOpposite());
|
||||
FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.SECONDARY_GLOVE).findFirst().ifPresent(bangle -> {
|
||||
renderBangleThirdPerson(bangle.stack(), stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm().getOpposite());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -82,14 +82,14 @@ public class BraceletFeatureRenderer<E extends LivingEntity> implements Accessor
|
|||
|
||||
@Override
|
||||
public void renderArm(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, E entity, ModelPart armModel, Arm side) {
|
||||
FriendshipBraceletItem.getWornBangles(entity, side == entity.getMainArm() ? TrinketsDelegate.MAINHAND : TrinketsDelegate.OFFHAND).findFirst().ifPresent(item -> {
|
||||
int j = ((DyeableItem)item.getItem()).getColor(item);
|
||||
FriendshipBraceletItem.getWornBangles(entity, side == entity.getMainArm() ? TrinketsDelegate.MAIN_GLOVE : TrinketsDelegate.SECONDARY_GLOVE).findFirst().ifPresent(item -> {
|
||||
int j = ((DyeableItem)item.stack().getItem()).getColor(item.stack());
|
||||
|
||||
boolean alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getModel().startsWith("slim");
|
||||
|
||||
BraceletModel model = alex ? alexModel : steveModel;
|
||||
|
||||
boolean glowing = ((GlowableItem)item.getItem()).isGlowing(item);
|
||||
boolean glowing = ((GlowableItem)item.stack().getItem()).isGlowing(item.stack());
|
||||
|
||||
if (MineLPDelegate.getInstance().getPlayerPonyRace((ClientPlayerEntity)entity).isEquine()) {
|
||||
stack.translate(side == Arm.LEFT ? 0.06 : -0.06, 0.3, 0);
|
||||
|
|
|
@ -36,7 +36,7 @@ public class GlassesFeatureRenderer<E extends LivingEntity> implements Accessory
|
|||
@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);
|
||||
ItemStack stack = GlassesItem.getForEntity(entity).stack();
|
||||
|
||||
if (!stack.isEmpty()) {
|
||||
Identifier texture = textures.computeIfAbsent(Registries.ITEM.getId(stack.getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png"));
|
||||
|
|
|
@ -42,7 +42,7 @@ public class PlayerPoser {
|
|||
boolean liftLeftArm = mainArm == Arm.LEFT || !ponyRace.isEquine();
|
||||
boolean liftRightArm = mainArm == Arm.RIGHT || !ponyRace.isEquine();
|
||||
|
||||
ItemStack glasses = GlassesItem.getForEntity(player);
|
||||
ItemStack glasses = GlassesItem.getForEntity(player).stack();
|
||||
ModelPart head = model.getHead();
|
||||
|
||||
if (context == Context.THIRD_PERSON && !player.isSneaking()) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.minelittlepony.unicopia.compat.trinkets;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -16,16 +18,17 @@ import net.minecraft.entity.mob.MobEntity;
|
|||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public interface TrinketsDelegate {
|
||||
Identifier MAINHAND = new Identifier("hand:glove");
|
||||
Identifier OFFHAND = new Identifier("offhand:glove");
|
||||
Identifier MAIN_GLOVE = new Identifier("hand:glove");
|
||||
Identifier SECONDARY_GLOVE = new Identifier("offhand:glove");
|
||||
Identifier NECKLACE = new Identifier("chest:necklace");
|
||||
Identifier FACE = new Identifier("head:face");
|
||||
|
||||
Set<Identifier> ALL = new TreeSet<>(List.of(MAINHAND, OFFHAND, NECKLACE, FACE));
|
||||
Set<Identifier> ALL = new TreeSet<>(List.of(MAIN_GLOVE, SECONDARY_GLOVE, NECKLACE, FACE));
|
||||
|
||||
TrinketsDelegate EMPTY = new TrinketsDelegate() {};
|
||||
|
||||
|
@ -61,8 +64,8 @@ public interface TrinketsDelegate {
|
|||
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
|
||||
: slot == MAIN_GLOVE ? EquipmentSlot.CHEST
|
||||
: slot == SECONDARY_GLOVE ? EquipmentSlot.OFFHAND
|
||||
: null;
|
||||
if (eq != null) {
|
||||
entity.equipStack(eq, stack);
|
||||
|
@ -70,19 +73,27 @@ public interface TrinketsDelegate {
|
|||
}
|
||||
|
||||
default Set<Identifier> getAvailableTrinketSlots(LivingEntity entity, Set<Identifier> probedSlots) {
|
||||
return probedSlots.stream().filter(slot -> getEquipped(entity, slot).anyMatch(ItemStack::isEmpty)).collect(Collectors.toSet());
|
||||
return probedSlots.stream().filter(slot -> getEquipped(entity, slot).map(EquippedStack::stack).anyMatch(ItemStack::isEmpty)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
default Stream<ItemStack> getEquipped(LivingEntity entity, Identifier slot) {
|
||||
default Stream<EquippedStack> getEquipped(LivingEntity entity, Identifier slot, TagKey<Item> tag) {
|
||||
return getEquipped(entity, slot, stack -> stack.isIn(tag));
|
||||
}
|
||||
|
||||
if (slot == FACE) {
|
||||
return Stream.of(entity.getEquippedStack(EquipmentSlot.HEAD));
|
||||
default Stream<EquippedStack> getEquipped(LivingEntity entity, Identifier slot) {
|
||||
return getEquipped(entity, slot, (Predicate<ItemStack>)null);
|
||||
}
|
||||
if (slot == NECKLACE || slot == MAINHAND) {
|
||||
return Stream.of(entity.getEquippedStack(EquipmentSlot.CHEST));
|
||||
|
||||
default Stream<EquippedStack> getEquipped(LivingEntity entity, Identifier slot, @Nullable Predicate<ItemStack> predicate) {
|
||||
|
||||
if (slot == FACE && (predicate == null || predicate.test(entity.getEquippedStack(EquipmentSlot.HEAD)))) {
|
||||
return Stream.of(new EquippedStack(entity, EquipmentSlot.HEAD));
|
||||
}
|
||||
if (slot == OFFHAND) {
|
||||
return Stream.of(entity.getOffHandStack());
|
||||
if ((slot == NECKLACE || slot == MAIN_GLOVE) && (predicate == null || predicate.test(entity.getEquippedStack(EquipmentSlot.CHEST)))) {
|
||||
return Stream.of(new EquippedStack(entity, EquipmentSlot.CHEST));
|
||||
}
|
||||
if (slot == SECONDARY_GLOVE && (predicate == null || predicate.test(entity.getEquippedStack(EquipmentSlot.OFFHAND)))) {
|
||||
return Stream.of(new EquippedStack(entity, EquipmentSlot.OFFHAND));
|
||||
}
|
||||
|
||||
return Stream.empty();
|
||||
|
@ -102,16 +113,24 @@ public interface TrinketsDelegate {
|
|||
|
||||
interface Inventory extends EntityConvertable<LivingEntity> {
|
||||
|
||||
default Stream<ItemStack> getEquippedStacks(Identifier slot) {
|
||||
default Stream<EquippedStack> getEquippedStacks(Identifier slot) {
|
||||
return TrinketsDelegate.getInstance(asEntity()).getEquipped(asEntity(), slot);
|
||||
}
|
||||
|
||||
default ItemStack getEquippedStack(Identifier slot) {
|
||||
return getEquippedStacks(slot).findFirst().orElse(ItemStack.EMPTY);
|
||||
default EquippedStack getEquippedStack(Identifier slot) {
|
||||
return getEquippedStacks(slot).findFirst().orElse(EquippedStack.EMPTY);
|
||||
}
|
||||
|
||||
default void equipStack(Identifier slot, ItemStack stack) {
|
||||
TrinketsDelegate.getInstance(asEntity()).setEquippedStack(asEntity(), slot, stack);
|
||||
}
|
||||
}
|
||||
|
||||
record EquippedStack(ItemStack stack, Runnable sendUpdate, Consumer<LivingEntity> breakStatusSender) {
|
||||
public static EquippedStack EMPTY = new EquippedStack(ItemStack.EMPTY, () -> {}, l -> {});
|
||||
|
||||
EquippedStack(LivingEntity entity, EquipmentSlot slot) {
|
||||
this(entity.getEquippedStack(slot), () -> {}, l -> l.sendEquipmentBreakStatus(slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
package com.minelittlepony.unicopia.compat.trinkets;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.container.SpellbookScreenHandler;
|
||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgTrinketBroken;
|
||||
import com.minelittlepony.unicopia.util.InventoryUtil;
|
||||
import dev.emi.trinkets.TrinketSlot;
|
||||
import dev.emi.trinkets.api.*;
|
||||
|
@ -80,8 +85,16 @@ public class TrinketsDelegateImpl implements TrinketsDelegate {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Stream<ItemStack> getEquipped(LivingEntity entity, Identifier slot) {
|
||||
return getInventory(entity, slot).stream().flatMap(InventoryUtil::stream).filter(s -> !s.isEmpty());
|
||||
public Stream<EquippedStack> getEquipped(LivingEntity entity, Identifier slot, @Nullable Predicate<ItemStack> predicate) {
|
||||
return getInventory(entity, slot).stream().flatMap(inventory -> {
|
||||
return InventoryUtil.stream(inventory).filter(s -> !s.isEmpty() && (predicate == null || predicate.test(s))).map(stack -> {
|
||||
ItemStack oldStack = stack.copy();
|
||||
return new EquippedStack(stack, inventory::markUpdate, l -> {
|
||||
inventory.markUpdate();
|
||||
Channel.SERVER_TRINKET_BROKEN.sendToSurroundingPlayers(new MsgTrinketBroken(oldStack, l.getId()), l);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -147,8 +147,8 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
|
||||
TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.FACE, 0, rightHandX, inventoryY + slotSpacing * 6).ifPresent(this::addSlot);
|
||||
TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.NECKLACE, 0, leftHandX, equipmentY + slotSpacing).ifPresent(this::addSlot);
|
||||
TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.MAINHAND, 0, leftHandX, equipmentY).ifPresent(this::addSlot);
|
||||
TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.OFFHAND, 0, rightHandX, equipmentY).ifPresent(this::addSlot);
|
||||
TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.MAIN_GLOVE, 0, leftHandX, equipmentY).ifPresent(this::addSlot);
|
||||
TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.SECONDARY_GLOVE, 0, rightHandX, equipmentY).ifPresent(this::addSlot);
|
||||
|
||||
addSlot(outputSlot = new OutputSlot(this, inventory.player, input, result, 0, gemPos.get(0)));
|
||||
|
||||
|
|
|
@ -371,8 +371,8 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
|||
}
|
||||
|
||||
if (magical.isIn(UTags.DamageTypes.BREAKS_SUNGLASSES)) {
|
||||
ItemStack glasses = GlassesItem.getForEntity(entity);
|
||||
if (glasses.getItem() == UItems.SUNGLASSES) {
|
||||
ItemStack glasses = GlassesItem.getForEntity(entity).stack();
|
||||
if (glasses.isOf(UItems.SUNGLASSES)) {
|
||||
ItemStack broken = UItems.BROKEN_SUNGLASSES.getDefaultStack();
|
||||
broken.setNbt(glasses.getNbt());
|
||||
TrinketsDelegate.getInstance(entity).setEquippedStack(entity, TrinketsDelegate.FACE, broken);
|
||||
|
@ -417,7 +417,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
|||
return StreamSupport.stream(entity.getArmorItems().spliterator(), false);
|
||||
}
|
||||
return Stream.concat(
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE),
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE).map(TrinketsDelegate.EquippedStack::stack),
|
||||
StreamSupport.stream(entity.getArmorItems().spliterator(), false)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
|||
import com.minelittlepony.unicopia.util.MeteorlogicalUtil;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.effect.StatusEffect;
|
||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||
|
@ -72,9 +71,7 @@ public class SunBlindnessStatusEffect extends StatusEffect {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.Items.SHADES)
|
||||
|| TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.Items.SHADES))
|
||||
|| entity.isSubmergedInWater()) {
|
||||
if (entity.isSubmergedInWater() || TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE, i -> i.isIn(UTags.Items.SHADES)).findAny().isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ import com.minelittlepony.unicopia.EquinePredicates;
|
|||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||
import com.minelittlepony.unicopia.entity.AmuletSelectors;
|
||||
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||
import com.minelittlepony.unicopia.entity.ai.ArenaAttackGoal;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.AmuletItem;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleSource;
|
||||
|
@ -63,7 +63,6 @@ import net.minecraft.entity.mob.HostileEntity;
|
|||
import net.minecraft.entity.passive.IronGolemEntity;
|
||||
import net.minecraft.entity.passive.MerchantEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
|
@ -484,9 +483,10 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
|||
player.sendMessage(Text.translatable("entity.unicopia.sombra.taunt"));
|
||||
}
|
||||
}
|
||||
ItemStack amulet = AmuletItem.getForEntity(player);
|
||||
if (amulet.isOf(UItems.ALICORN_AMULET)) {
|
||||
amulet.decrement(1);
|
||||
TrinketsDelegate.EquippedStack amulet = UItems.ALICORN_AMULET.getForEntity(player);
|
||||
if (!amulet.stack().isEmpty()) {
|
||||
amulet.stack().decrement(1);
|
||||
amulet.sendUpdate();
|
||||
}
|
||||
}
|
||||
boolean damaged = super.damage(source, amount);
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.minelittlepony.unicopia.advancement.UCriteria;
|
|||
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.compat.ad_astra.OxygenApi;
|
||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||
import com.minelittlepony.unicopia.entity.*;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.entity.duck.LivingEntityDuck;
|
||||
|
@ -38,12 +39,10 @@ import net.fabricmc.fabric.api.tag.convention.v1.ConventionalBlockTags;
|
|||
import net.minecraft.block.*;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LightningEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
|
@ -499,8 +498,8 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
|||
|
||||
private void tickArtificialFlight(MutableVector velocity) {
|
||||
if (ticksInAir % 10 == 0 && !entity.getWorld().isClient) {
|
||||
ItemStack stack = AmuletItem.getForEntity(entity);
|
||||
if (ChargeableItem.getEnergy(stack) < 9) {
|
||||
TrinketsDelegate.EquippedStack stack = AmuletItem.get(entity);
|
||||
if (ChargeableItem.getEnergy(stack.stack()) < 9) {
|
||||
playSound(USounds.ITEM_ICARUS_WINGS_WARN, 0.13F, 0.5F);
|
||||
}
|
||||
|
||||
|
@ -517,10 +516,10 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
|||
minDamage *= 3;
|
||||
}
|
||||
|
||||
ChargeableItem.consumeEnergy(stack, energyConsumed);
|
||||
ChargeableItem.consumeEnergy(stack.stack(), energyConsumed);
|
||||
|
||||
if (entity.getWorld().random.nextInt(damageInterval) == 0) {
|
||||
stack.damage(minDamage + entity.getWorld().random.nextInt(50), entity, e -> e.sendEquipmentBreakStatus(EquipmentSlot.CHEST));
|
||||
stack.stack().damage(minDamage + entity.getWorld().random.nextInt(50), (LivingEntity)entity, stack.breakStatusSender());
|
||||
}
|
||||
|
||||
if (!lastFlightType.canFly()) {
|
||||
|
|
|
@ -484,6 +484,9 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
|||
AmuletSelectors.PEARL_NECKLACE.test(entity) ? suppressedRace.or(Race.SEAPONY) : null
|
||||
);
|
||||
UCriteria.PLAYER_CHANGE_RACE.trigger(entity);
|
||||
|
||||
var hasNecklace = AmuletSelectors.PEARL_NECKLACE.test(entity);
|
||||
System.out.println(hasNecklace);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -526,7 +529,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
|||
}
|
||||
|
||||
if (getObservedSpecies() == Race.BAT && !entity.hasPortalCooldown()) {
|
||||
boolean hasShades = TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(s -> s.isIn(UTags.Items.SHADES));
|
||||
boolean hasShades = TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(s -> s.stack().isIn(UTags.Items.SHADES));
|
||||
if (!this.hasShades && hasShades && getObservedSpecies() == Race.BAT) {
|
||||
UCriteria.WEAR_SHADES.trigger(entity);
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
|
|||
|
||||
// bind to the player after 3 days
|
||||
if (daysAttached >= 3 && !pony.asEntity().isCreative()) {
|
||||
stack = living.getArmour().getEquippedStack(TrinketsDelegate.NECKLACE);
|
||||
stack = living.getArmour().getEquippedStack(TrinketsDelegate.NECKLACE).stack();
|
||||
if (stack.getItem() == this && !EnchantmentHelper.hasBindingCurse(stack)) {
|
||||
pony.playSound(USounds.ITEM_ALICORN_AMULET_HALLUCINATION, 3, 1);
|
||||
stack = stack.copy();
|
||||
|
|
|
@ -86,7 +86,13 @@ public class AmuletItem extends WearableItem implements ChargeableItem {
|
|||
}
|
||||
|
||||
public final boolean isApplicable(LivingEntity entity) {
|
||||
return isApplicable(getForEntity(entity));
|
||||
return !getForEntity(entity).stack().isEmpty();
|
||||
}
|
||||
|
||||
public TrinketsDelegate.EquippedStack getForEntity(LivingEntity entity) {
|
||||
return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE, this::isApplicable)
|
||||
.findFirst()
|
||||
.orElse(TrinketsDelegate.EquippedStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,11 +100,10 @@ public class AmuletItem extends WearableItem implements ChargeableItem {
|
|||
return maxEnergy;
|
||||
}
|
||||
|
||||
public static ItemStack getForEntity(LivingEntity entity) {
|
||||
public static TrinketsDelegate.EquippedStack get(LivingEntity entity) {
|
||||
return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE)
|
||||
.filter(stack -> stack.getItem() instanceof AmuletItem)
|
||||
.findFirst()
|
||||
.orElse(ItemStack.EMPTY);
|
||||
.orElse(TrinketsDelegate.EquippedStack.EMPTY);
|
||||
}
|
||||
|
||||
public static class ModifiersBuilder {
|
||||
|
|
|
@ -69,7 +69,7 @@ public class BellItem extends Item implements ChargeableItem {
|
|||
@Override
|
||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
ItemStack offhandStack = AmuletItem.getForEntity(player);
|
||||
ItemStack offhandStack = AmuletItem.get(player).stack();
|
||||
|
||||
if (!(offhandStack.getItem() instanceof ChargeableItem)) {
|
||||
offhandStack = player.getStackInHand(hand == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND);
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.item;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -120,28 +121,36 @@ public class FriendshipBraceletItem extends WearableItem implements DyeableItem,
|
|||
|
||||
public static boolean isComrade(Owned<?> caster, Entity entity) {
|
||||
return entity instanceof LivingEntity l && caster.getMasterId()
|
||||
.filter(id -> getWornBangles(l).anyMatch(stack -> isSignedBy(stack, id)))
|
||||
.filter(id -> getWornBangles(l).anyMatch(stack -> isSignedBy(stack.stack(), id)))
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
public static boolean isComrade(UUID signator, Entity entity) {
|
||||
return entity instanceof LivingEntity l && getWornBangles(l).anyMatch(stack -> isSignedBy(stack, signator));
|
||||
return entity instanceof LivingEntity l && getWornBangles(l, stack -> isSignedBy(stack, signator)).findAny().isPresent();
|
||||
}
|
||||
|
||||
public static Stream<Pony> getPartyMembers(Caster<?> caster, double radius) {
|
||||
return Pony.stream(caster.findAllEntitiesInRange(radius, entity -> isComrade(caster, entity)));
|
||||
}
|
||||
|
||||
public static Stream<ItemStack> getWornBangles(LivingEntity entity) {
|
||||
private static final Predicate<ItemStack> IS_BANGLE = stack -> stack.isOf(UItems.FRIENDSHIP_BRACELET);
|
||||
|
||||
public static Stream<TrinketsDelegate.EquippedStack> getWornBangles(LivingEntity entity) {
|
||||
return Stream.concat(
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.MAINHAND),
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.OFFHAND)
|
||||
).filter(stack -> stack.getItem() == UItems.FRIENDSHIP_BRACELET);
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.MAIN_GLOVE, IS_BANGLE),
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.SECONDARY_GLOVE, IS_BANGLE)
|
||||
);
|
||||
}
|
||||
|
||||
public static Stream<ItemStack> getWornBangles(LivingEntity entity, Identifier slot) {
|
||||
return TrinketsDelegate.getInstance(entity)
|
||||
.getEquipped(entity, slot)
|
||||
.filter(stack -> stack.getItem() == UItems.FRIENDSHIP_BRACELET);
|
||||
public static Stream<TrinketsDelegate.EquippedStack> getWornBangles(LivingEntity entity, @Nullable Predicate<ItemStack> predicate) {
|
||||
predicate = predicate == null ? IS_BANGLE : IS_BANGLE.and(predicate);
|
||||
return Stream.concat(
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.MAIN_GLOVE, predicate),
|
||||
TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.SECONDARY_GLOVE, predicate)
|
||||
);
|
||||
}
|
||||
|
||||
public static Stream<TrinketsDelegate.EquippedStack> getWornBangles(LivingEntity entity, Identifier slot) {
|
||||
return TrinketsDelegate.getInstance(entity).getEquipped(entity, slot, IS_BANGLE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,13 +25,12 @@ public class GlassesItem extends WearableItem {
|
|||
}
|
||||
|
||||
public boolean isApplicable(LivingEntity entity) {
|
||||
return getForEntity(entity).getItem() == this;
|
||||
return getForEntity(entity).stack().isOf(this);
|
||||
}
|
||||
|
||||
public static ItemStack getForEntity(LivingEntity entity) {
|
||||
return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE)
|
||||
.filter(stack -> stack.getItem() instanceof GlassesItem)
|
||||
public static TrinketsDelegate.EquippedStack getForEntity(LivingEntity entity) {
|
||||
return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE, stack -> stack.getItem() instanceof GlassesItem)
|
||||
.findFirst()
|
||||
.orElse(ItemStack.EMPTY);
|
||||
.orElse(TrinketsDelegate.EquippedStack.EMPTY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,6 @@ public class PegasusAmuletItem extends AmuletItem implements ItemTracker.Trackab
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(ItemStack stack) {
|
||||
return super.isApplicable(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultCharge() {
|
||||
return getMaxCharge() / 2;
|
||||
|
|
|
@ -220,6 +220,7 @@ public interface UItems {
|
|||
.rarity(Rarity.UNCOMMON), 0), ItemGroups.TOOLS);
|
||||
AmuletItem PEARL_NECKLACE = register("pearl_necklace", new AmuletItem(new FabricItemSettings()
|
||||
.maxCount(1)
|
||||
.maxDamage(4)
|
||||
.rarity(Rarity.UNCOMMON), 0), ItemGroups.TOOLS);
|
||||
|
||||
GlassesItem SUNGLASSES = register("sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT);
|
||||
|
|
|
@ -37,6 +37,7 @@ public interface Channel {
|
|||
S2CPacketType<MsgSkyAngle> SERVER_SKY_ANGLE = SimpleNetworking.serverToClient(Unicopia.id("sky_angle"), MsgSkyAngle::new);
|
||||
S2CPacketType<MsgConfigurationChange> CONFIGURATION_CHANGE = SimpleNetworking.serverToClient(Unicopia.id("config"), MsgConfigurationChange::new);
|
||||
S2CPacketType<MsgZapAppleStage> SERVER_ZAP_STAGE = SimpleNetworking.serverToClient(Unicopia.id("zap_stage"), MsgZapAppleStage::new);
|
||||
S2CPacketType<MsgTrinketBroken> SERVER_TRINKET_BROKEN = SimpleNetworking.serverToClient(Unicopia.id("trinket_broken"), MsgTrinketBroken::new);
|
||||
|
||||
static void bootstrap() {
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.minelittlepony.unicopia.network;
|
||||
|
||||
import com.sollace.fabwork.api.packets.Packet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* Sent to the client when an item equipped in a trinket slot breaks
|
||||
*/
|
||||
public record MsgTrinketBroken (ItemStack stack, int entityId) implements Packet<PlayerEntity> {
|
||||
public MsgTrinketBroken(PacketByteBuf buffer) {
|
||||
this(buffer.readItemStack(), buffer.readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeItemStack(stack);
|
||||
buffer.writeInt(entityId);
|
||||
}
|
||||
}
|
|
@ -20,8 +20,14 @@ import com.minelittlepony.unicopia.network.*;
|
|||
import com.minelittlepony.unicopia.network.MsgCasterLookRequest.Reply;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.particle.ItemStackParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class ClientNetworkHandlerImpl {
|
||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
@ -36,6 +42,7 @@ public class ClientNetworkHandlerImpl {
|
|||
Channel.SERVER_ZAP_STAGE.receiver().addPersistentListener(this::handleZapStage);
|
||||
Channel.SERVER_PLAYER_ANIMATION_CHANGE.receiver().addPersistentListener(this::handlePlayerAnimation);
|
||||
Channel.SERVER_REQUEST_PLAYER_LOOK.receiver().addPersistentListener(this::handleCasterLookRequest);
|
||||
Channel.SERVER_TRINKET_BROKEN.receiver().addPersistentListener(this::handleTrinketBroken);
|
||||
Channel.CONFIGURATION_CHANGE.receiver().addPersistentListener(this::handleConfigurationChange);
|
||||
}
|
||||
|
||||
|
@ -96,6 +103,37 @@ public class ClientNetworkHandlerImpl {
|
|||
Channel.CLIENT_CASTER_LOOK.sendToServer(new Reply(packet.spellId(), Rot.of(player)));
|
||||
}
|
||||
|
||||
private void handleTrinketBroken(PlayerEntity player, MsgTrinketBroken packet) {
|
||||
if (player.getWorld().getEntityById(packet.entityId()) instanceof LivingEntity sender) {
|
||||
ItemStack stack = packet.stack();
|
||||
if (!stack.isEmpty()) {
|
||||
if (!sender.isSilent()) {
|
||||
sender.getWorld().playSound(
|
||||
sender.getX(), sender.getY(), sender.getZ(),
|
||||
SoundEvents.ENTITY_ITEM_BREAK, sender.getSoundCategory(),
|
||||
0.8F,
|
||||
0.8F + sender.getWorld().random.nextFloat() * 0.4F,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
int count = 5;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
Vec3d vec3d = new Vec3d((sender.getWorld().random.nextFloat() - 0.5) * 0.1, Math.random() * 0.1 + 0.1, 0.0);
|
||||
vec3d = vec3d.rotateX(-sender.getPitch() * (float) (Math.PI / 180.0));
|
||||
vec3d = vec3d.rotateY(-sender.getYaw() * (float) (Math.PI / 180.0));
|
||||
double d = (-sender.getWorld().random.nextFloat()) * 0.6 - 0.3;
|
||||
Vec3d vec3d2 = new Vec3d((sender.getWorld().random.nextFloat() - 0.5) * 0.3, d, 0.6);
|
||||
vec3d2 = vec3d2.rotateX(-sender.getPitch() * (float) (Math.PI / 180.0));
|
||||
vec3d2 = vec3d2.rotateY(-sender.getYaw() * (float) (Math.PI / 180.0));
|
||||
vec3d2 = vec3d2.add(sender.getX(), sender.getEyeY(), sender.getZ());
|
||||
sender.getWorld().addParticle(new ItemStackParticleEffect(ParticleTypes.ITEM, stack), vec3d2.x, vec3d2.y, vec3d2.z, vec3d.x, vec3d.y + 0.05, vec3d.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConfigurationChange(PlayerEntity sender, MsgConfigurationChange packet) {
|
||||
InteractionManager.getInstance().setSyncedConfig(packet.config());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue