Updating to 1.21 (part 6)

This commit is contained in:
Sollace 2024-10-01 02:45:58 +01:00
parent 5037ee2bc1
commit b033d1dc7a
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
34 changed files with 382 additions and 336 deletions

View file

@ -12,7 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.AmuletItem; import com.minelittlepony.unicopia.item.AmuletItem;
import com.minelittlepony.unicopia.item.ChargeableItem; import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.util.TraceHelper; import com.minelittlepony.unicopia.util.TraceHelper;
import com.minelittlepony.unicopia.util.VecHelper; import com.minelittlepony.unicopia.util.VecHelper;
@ -56,7 +56,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
if (amulet.getResult().isAccepted()) { if (amulet.getResult().isAccepted()) {
float manaLevel = player.getMagicalReserves().getMana().get(); float manaLevel = player.getMagicalReserves().getMana().get();
return Math.min(manaLevel, ((AmuletItem)amulet.getValue().getItem()).getChargeRemainder(amulet.getValue())); return Math.min(manaLevel, Charges.of(amulet.getValue()).energy());
} }
TypedActionResult<CustomisedSpellType<?>> spell = player.getCharms().getSpellInHand(false); TypedActionResult<CustomisedSpellType<?>> spell = player.getCharms().getSpellInHand(false);
@ -84,13 +84,11 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
if (amulet.getResult().isAccepted()) { if (amulet.getResult().isAccepted()) {
ItemStack stack = amulet.getValue(); ItemStack stack = amulet.getValue();
ChargeableItem item = (ChargeableItem)stack.getItem(); if (Charges.of(stack).canHoldCharge()) {
int amount = -(int)Math.min(player.getMagicalReserves().getMana().get(), Charges.of(stack).energy());
if (item.canCharge(stack)) {
float amount = -Math.min(player.getMagicalReserves().getMana().get(), item.getChargeRemainder(stack));
if (amount < 0) { if (amount < 0) {
ChargeableItem.consumeEnergy(stack, amount); Charges.discharge(stack, amount);
player.getMagicalReserves().getMana().add(amount); player.getMagicalReserves().getMana().add(amount);
player.asWorld().playSoundFromEntity(null, player.asEntity(), USounds.ITEM_AMULET_RECHARGE, SoundCategory.PLAYERS, 1, 1); player.asWorld().playSoundFromEntity(null, player.asEntity(), USounds.ITEM_AMULET_RECHARGE, SoundCategory.PLAYERS, 1, 1);
} }
@ -144,7 +142,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
ItemStack stack = player.asEntity().getStackInHand(Hand.MAIN_HAND); ItemStack stack = player.asEntity().getStackInHand(Hand.MAIN_HAND);
if (stack.getItem() instanceof AmuletItem) { if (stack.getItem() instanceof AmuletItem) {
if (((AmuletItem)stack.getItem()).isChargable()) { if (Charges.of(stack).canHoldCharge()) {
return TypedActionResult.consume(stack); return TypedActionResult.consume(stack);
} }

View file

@ -23,7 +23,6 @@ import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.projectile.ProjectileUtil;
import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.server.world.Ether;
import com.minelittlepony.unicopia.util.ColorHelper;
import com.minelittlepony.unicopia.util.Lerp; import com.minelittlepony.unicopia.util.Lerp;
import com.minelittlepony.unicopia.util.shape.Sphere; import com.minelittlepony.unicopia.util.shape.Sphere;
@ -40,6 +39,7 @@ import net.minecraft.entity.passive.PassiveEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity; import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.util.math.ColorHelper.Argb;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -91,7 +91,7 @@ public class ShieldSpell extends AbstractSpell {
source.spawnParticles(origin, new Sphere(true, radius.getValue()), (int)(radius.getValue() * 2), pos -> { source.spawnParticles(origin, new Sphere(true, radius.getValue()), (int)(radius.getValue() * 2), pos -> {
int hornColor = MineLPDelegate.getInstance().getMagicColor(source.getOriginatingCaster().asEntity()); int hornColor = MineLPDelegate.getInstance().getMagicColor(source.getOriginatingCaster().asEntity());
source.addParticle(new MagicParticleEffect(ColorHelper.lerp(0.6F, getType().getColor(), hornColor)), pos, Vec3d.ZERO); source.addParticle(new MagicParticleEffect(Argb.lerp(0.6F, getType().getColor(), hornColor)), pos, Vec3d.ZERO);
if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) { if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) {
ParticleUtils.spawnParticle(source.asWorld(), new LightningBoltParticleEffect(true, 3, 2, 0.1F, Optional.empty()), pos, Vec3d.ZERO); ParticleUtils.spawnParticle(source.asWorld(), new LightningBoltParticleEffect(true, 3, 2, 0.1F, Optional.empty()), pos, Vec3d.ZERO);

View file

@ -100,7 +100,6 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
} }
} }
@Deprecated
@Override @Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
if (state.get(CONSUMING)) { if (state.get(CONSUMING)) {

View file

@ -31,10 +31,10 @@ import com.minelittlepony.unicopia.client.render.spell.SpellRendererFactory;
import com.minelittlepony.unicopia.entity.mob.ButterflyEntity; import com.minelittlepony.unicopia.entity.mob.ButterflyEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.item.ButterflyItem; import com.minelittlepony.unicopia.item.ButterflyItem;
import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.EnchantableItem; import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.FancyBedItem; import com.minelittlepony.unicopia.item.FancyBedItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Appearance;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
import com.terraformersmc.terraform.boat.api.client.TerraformBoatClientHelper; import com.terraformersmc.terraform.boat.api.client.TerraformBoatClientHelper;
@ -207,7 +207,7 @@ public interface URenderers {
VertexConsumerProvider.Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); VertexConsumerProvider.Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers();
ClientWorld world = MinecraftClient.getInstance().world; ClientWorld world = MinecraftClient.getInstance().world;
if (ChameleonItem.hasAppearance(stack)) { if (Appearance.hasAppearance(stack)) {
matrices.push(); matrices.push();
if (mode.isFirstPerson()) { if (mode.isFirstPerson()) {
matrices.translate(0.05, 0.06, 0.06); matrices.translate(0.05, 0.06, 0.06);
@ -221,9 +221,7 @@ public interface URenderers {
float scale = 0.5F; float scale = 0.5F;
matrices.scale(scale, scale, scale); matrices.scale(scale, scale, scale);
renderer.renderItem(Appearance.upwrapAppearance(stack), mode, light, overlay, matrices, immediate, world, 0);
ItemStack appearance = ChameleonItem.getAppearanceStack(stack);
renderer.renderItem(appearance, mode, light, overlay, matrices, immediate, world, 0);
matrices.pop(); matrices.pop();
} }
renderer.renderItem(UItems.EMPTY_JAR.getDefaultStack(), mode, light, overlay, matrices, vertices, world, 0); renderer.renderItem(UItems.EMPTY_JAR.getDefaultStack(), mode, light, overlay, matrices, vertices, world, 0);

View file

@ -8,7 +8,6 @@ import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.client.gui.*; import com.minelittlepony.unicopia.client.gui.*;
import com.minelittlepony.unicopia.entity.player.*; import com.minelittlepony.unicopia.entity.player.*;
import com.minelittlepony.unicopia.util.ColorHelper;
import com.sollace.romanizer.api.Romanizer; import com.sollace.romanizer.api.Romanizer;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@ -17,6 +16,7 @@ import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper.Argb;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
public class SpellbookProfilePageContent implements SpellbookChapterList.Content { public class SpellbookProfilePageContent implements SpellbookChapterList.Content {
@ -74,8 +74,8 @@ public class SpellbookProfilePageContent implements SpellbookChapterList.Content
currentScaledLevel, currentScaledLevel,
currentCorruption currentCorruption
), SpellbookScreen.TITLE_X, y + 13, 0.8F, ), SpellbookScreen.TITLE_X, y + 13, 0.8F,
ColorHelper.lerp(currentCorruption, Argb.lerp(currentCorruption,
ColorHelper.lerp(currentScaledLevel, 0xAA0040FF, 0xAAA0AA40), Argb.lerp(currentScaledLevel, 0xAA0040FF, 0xAAA0AA40),
0xAAFF0000 0xAAFF0000
) )
); );
@ -106,7 +106,7 @@ public class SpellbookProfilePageContent implements SpellbookChapterList.Content
int xpColor = 0xAA0040FF | ((int)((0.3F + 0.7F * xpPercentage) * 0xFF) & 0xFF) << 16; int xpColor = 0xAA0040FF | ((int)((0.3F + 0.7F * xpPercentage) * 0xFF) & 0xFF) << 16;
int manaColor = 0xFF00F040; int manaColor = 0xFF00F040;
if (pony.getSpellSlot().get(SpellPredicate.IS_CORRUPTING).isPresent()) { if (pony.getSpellSlot().get(SpellPredicate.IS_CORRUPTING).isPresent()) {
manaColor = ColorHelper.lerp(Math.abs(MathHelper.sin(pony.asEntity().age / 15F)), manaColor, 0xFF0030F0); manaColor = Argb.lerp(Math.abs(MathHelper.sin(pony.asEntity().age / 15F)), manaColor, 0xFF0030F0);
} }
manaColor |= (int)((0.3F + 0.7F * alphaF) * 0x40) << 16; manaColor |= (int)((0.3F + 0.7F * alphaF) * 0x40) << 16;
@ -120,10 +120,10 @@ public class SpellbookProfilePageContent implements SpellbookChapterList.Content
growth = MathHelper.sin(delta / 10F) * 2; growth = MathHelper.sin(delta / 10F) * 2;
int bandAColor = ColorHelper.lerp(currentCorruption, 0xAAFFAA60, 0xFF000030); int bandAColor = Argb.lerp(currentCorruption, 0xAAFFAA60, 0xFF000030);
int bandBColor = ColorHelper.lerp(currentCorruption, 0xFFFFFF40, 0x00000020); int bandBColor = Argb.lerp(currentCorruption, 0xFFFFFF40, 0x00000020);
float glowSize = ColorHelper.lerp(currentCorruption, 8, -8); float glowSize = Argb.lerp(currentCorruption, 8, -8);
for (int i = 0; i < rayCount; i++) { for (int i = 0; i < rayCount; i++) {
double rad = (radius + glowSize) * 0.8F + growth - (i % 2) * 5; double rad = (radius + glowSize) * 0.8F + growth - (i % 2) * 5;

View file

@ -11,7 +11,6 @@ import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.PlayerScreenHandler;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.math.ColorHelper.Argb; import net.minecraft.util.math.ColorHelper.Argb;
public class FairyEntityRenderer extends MobEntityRenderer<FairyEntity, FairyEntityRenderer.Model> { public class FairyEntityRenderer extends MobEntityRenderer<FairyEntity, FairyEntityRenderer.Model> {

View file

@ -5,6 +5,7 @@ import net.minecraft.client.sound.MovingSoundInstance;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
public abstract class FadeOutSoundInstance extends MovingSoundInstance { public abstract class FadeOutSoundInstance extends MovingSoundInstance {
@ -30,6 +31,12 @@ public abstract class FadeOutSoundInstance extends MovingSoundInstance {
setTargetVolume(volume); setTargetVolume(volume);
} }
protected void setPosition(Vec3d pos) {
x = pos.x;
y = pos.y;
z = pos.z;
}
@Override @Override
public boolean shouldAlwaysPlay() { public boolean shouldAlwaysPlay() {
return true; return true;

View file

@ -5,7 +5,6 @@ import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
public class MagicAuraSoundInstance extends FadeOutSoundInstance { public class MagicAuraSoundInstance extends FadeOutSoundInstance {
@ -16,21 +15,14 @@ public class MagicAuraSoundInstance extends FadeOutSoundInstance {
super(USounds.ITEM_MAGIC_AURA, category, 1, random); super(USounds.ITEM_MAGIC_AURA, category, 1, random);
this.relative = false; this.relative = false;
this.living = living; this.living = living;
setPosition(living.getOriginVector());
Vec3d pos = living.getOriginVector();
x = pos.x;
y = pos.y;
z = pos.z;
} }
@Override @Override
protected boolean shouldKeepPlaying() { protected boolean shouldKeepPlaying() {
var data = living.getEnchants().getOrEmpty(UEnchantments.GEM_FINDER); var data = living.getEnchants().getOrEmpty(UEnchantments.GEM_FINDER);
Vec3d pos = living.getOriginVector(); setPosition(living.getOriginVector());
x = pos.x;
y = pos.y;
z = pos.z;
if (!living.asEntity().isRemoved() && data.isPresent()) { if (!living.asEntity().isRemoved() && data.isPresent()) {
float level = data.get().level; float level = data.get().level;

View file

@ -389,6 +389,7 @@ public class ButterflyEntity extends AmbientEntity {
public static final Variant[] VALUES = Variant.values(); public static final Variant[] VALUES = Variant.values();
@SuppressWarnings("deprecation")
public static final EnumCodec<Variant> CODEC = StringIdentifiable.createCodec(Variant::values); public static final EnumCodec<Variant> CODEC = StringIdentifiable.createCodec(Variant::values);
public static final PacketCodec<ByteBuf, Variant> PACKET_CODEC = PacketCodecs.indexed(i -> VALUES[i], Variant::ordinal); public static final PacketCodec<ByteBuf, Variant> PACKET_CODEC = PacketCodecs.indexed(i -> VALUES[i], Variant::ordinal);

View file

@ -199,12 +199,14 @@ public class Acrobatics implements Tickable, NbtSerialisable {
@Override @Override
public void toNBT(NbtCompound compound, WrapperLookup lookup) { public void toNBT(NbtCompound compound, WrapperLookup lookup) {
compound.putInt("ticksHanging", ticksHanging); compound.putInt("ticksHanging", ticksHanging);
BLOCK_POS.writeOptional("hangingPosition", compound, getHangingPosition(), lookup); getHangingPosition().ifPresent(pos -> {
compound.put("hangingPosition", NbtSerialisable.encode(BlockPos.CODEC, pos));
});
} }
@Override @Override
public void fromNBT(NbtCompound compound, WrapperLookup lookup) { public void fromNBT(NbtCompound compound, WrapperLookup lookup) {
ticksHanging = compound.getInt("ticksHanging"); ticksHanging = compound.getInt("ticksHanging");
hangingPos.set(NbtSerialisable.BLOCK_POS.readOptional("hangingPosition", compound, lookup)); hangingPos.set(NbtSerialisable.decode(BlockPos.CODEC, compound.get("hangingPosition")));
} }
} }

View file

@ -21,8 +21,8 @@ import com.minelittlepony.unicopia.entity.effect.EffectUtils;
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
import com.minelittlepony.unicopia.input.Heuristic; import com.minelittlepony.unicopia.input.Heuristic;
import com.minelittlepony.unicopia.item.AmuletItem; import com.minelittlepony.unicopia.item.AmuletItem;
import com.minelittlepony.unicopia.item.ChargeableItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.Channel;
@ -504,7 +504,8 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
private void tickArtificialFlight(MutableVector velocity) { private void tickArtificialFlight(MutableVector velocity) {
if (ticksInAir % 10 == 0 && !entity.getWorld().isClient) { if (ticksInAir % 10 == 0 && !entity.getWorld().isClient) {
TrinketsDelegate.EquippedStack stack = AmuletItem.get(entity); TrinketsDelegate.EquippedStack stack = AmuletItem.get(entity);
if (ChargeableItem.getEnergy(stack.stack()) < 9) { Charges charges = Charges.of(stack.stack());
if (charges.canHoldCharge() && charges.getPercentage() < 0.1F) {
playSound(USounds.ITEM_ICARUS_WINGS_WARN, 0.13F, 0.5F); playSound(USounds.ITEM_ICARUS_WINGS_WARN, 0.13F, 0.5F);
} }
@ -521,7 +522,9 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
minDamage *= 3; minDamage *= 3;
} }
ChargeableItem.consumeEnergy(stack.stack(), energyConsumed); if (charges.canHoldCharge()) {
Charges.discharge(stack.stack(), (int)energyConsumed);
}
if (entity.getWorld().random.nextInt(damageInterval) == 0) { if (entity.getWorld().random.nextInt(damageInterval) == 0) {
stack.stack().damage(minDamage + entity.getWorld().random.nextInt(50), (ServerWorld)entity.getWorld(), (ServerPlayerEntity)entity, stack.breakStatusSender()); stack.stack().damage(minDamage + entity.getWorld().random.nextInt(50), (ServerWorld)entity.getWorld(), (ServerPlayerEntity)entity, stack.breakStatusSender());

View file

@ -2,10 +2,7 @@ package com.minelittlepony.unicopia.item;
import java.util.*; import java.util.*;
import org.jetbrains.annotations.Nullable;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMultimap;
import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
@ -17,6 +14,7 @@ import com.minelittlepony.unicopia.entity.effect.UEffects;
import com.minelittlepony.unicopia.entity.mob.SombraEntity; import com.minelittlepony.unicopia.entity.mob.SombraEntity;
import com.minelittlepony.unicopia.entity.mob.SpellbookEntity; import com.minelittlepony.unicopia.entity.mob.SpellbookEntity;
import com.minelittlepony.unicopia.entity.player.*; import com.minelittlepony.unicopia.entity.player.*;
import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
@ -30,9 +28,7 @@ import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.EnchantmentEffectComponentTypes; import net.minecraft.component.EnchantmentEffectComponentTypes;
import net.minecraft.component.type.ItemEnchantmentsComponent;
import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments; import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.*; import net.minecraft.entity.*;
@ -49,7 +45,6 @@ import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.DamageTypeTags; import net.minecraft.registry.tag.DamageTypeTags;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@ -63,7 +58,7 @@ import net.minecraft.world.LocalDifficulty;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.World.ExplosionSourceType; import net.minecraft.world.World.ExplosionSourceType;
public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackable, ItemImpl.ClingyItem, ItemImpl.GroundTickCallback { public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackable, ItemImpl.ClingyItem, ItemImpl.GroundTickCallback, DamageChecker {
private static final Identifier EFFECT_ID = Unicopia.id("alicorn_amulet_modifiers"); private static final Identifier EFFECT_ID = Unicopia.id("alicorn_amulet_modifiers");
private static final Object2FloatMap<RegistryEntry<EntityAttribute>> EFFECT_SCALES = Object2FloatMaps.unmodifiable(new Object2FloatOpenHashMap<>(Map.of( private static final Object2FloatMap<RegistryEntry<EntityAttribute>> EFFECT_SCALES = Object2FloatMaps.unmodifiable(new Object2FloatOpenHashMap<>(Map.of(
EntityAttributes.GENERIC_ATTACK_DAMAGE, 0.2F, EntityAttributes.GENERIC_ATTACK_DAMAGE, 0.2F,
@ -104,7 +99,7 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
} }
@Override @Override
public boolean damage(DamageSource source) { public boolean takesDamageFrom(DamageSource source) {
return source.isIn(DamageTypeTags.BYPASSES_INVULNERABILITY); return source.isIn(DamageTypeTags.BYPASSES_INVULNERABILITY);
} }
@ -338,10 +333,8 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
for (Entity target : VecHelper.findInRange(entity, entity.getWorld(), entity.getPos(), 10, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR)) { for (Entity target : VecHelper.findInRange(entity, entity.getWorld(), entity.getPos(), 10, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR)) {
if (target instanceof LivingEntity l) { if (target instanceof LivingEntity l) {
for (ItemStack equipment : l.getEquippedItems()) { for (ItemStack equipment : l.getEquippedItems()) {
if (equipment.getItem() == UItems.GROGARS_BELL) { if (equipment.isOf(UItems.GROGARS_BELL)) {
ChargeableItem chargeable = (ChargeableItem)UItems.GROGARS_BELL; if (Charges.discharge(equipment, 3)) {
if (chargeable.hasCharge(equipment)) {
ChargeableItem.consumeEnergy(equipment, 3);
ParticleUtils.spawnParticle(entity.getWorld(), ParticleUtils.spawnParticle(entity.getWorld(),
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, entity, 0.4F) new FollowingParticleEffect(UParticles.HEALTH_DRAIN, entity, 0.4F)
.withChild(ParticleTypes.COMPOSTER), target.getEyePos(), Vec3d.ZERO); .withChild(ParticleTypes.COMPOSTER), target.getEyePos(), Vec3d.ZERO);

View file

@ -4,6 +4,8 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate; import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.component.type.AttributeModifiersComponent; import net.minecraft.component.type.AttributeModifiersComponent;
@ -22,14 +24,15 @@ import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public class AmuletItem extends WearableItem implements ChargeableItem { public class AmuletItem extends WearableItem {
public static final Identifier AMULET_MODIFIERS_ID = Unicopia.id("amulet_modifiers"); public static final Identifier AMULET_MODIFIERS_ID = Unicopia.id("amulet_modifiers");
private final int maxEnergy;
public AmuletItem(Item.Settings settings, int maxEnergy) { public AmuletItem(Item.Settings settings, int maxEnergy) {
super(settings.component(UDataComponentTypes.CHARGES, Charges.of(maxEnergy, maxEnergy)));
}
public AmuletItem(Item.Settings settings) {
super(settings); super(settings);
this.maxEnergy = maxEnergy;
} }
public AmuletItem(Item.Settings settings, int maxEnergy, AttributeModifiersComponent modifiers) { public AmuletItem(Item.Settings settings, int maxEnergy, AttributeModifiersComponent modifiers) {
@ -49,9 +52,7 @@ public class AmuletItem extends WearableItem implements ChargeableItem {
list.add(compiled); list.add(compiled);
} }
if (isChargable()) { Charges.of(stack).appendTooltip(context, list::add, type);
list.add(Text.translatable("item.unicopia.amulet.energy", (int)Math.floor(ChargeableItem.getEnergy(stack)), getMaxCharge()));
}
} }
@Override @Override
@ -66,11 +67,11 @@ public class AmuletItem extends WearableItem implements ChargeableItem {
@Override @Override
public boolean hasGlint(ItemStack stack) { public boolean hasGlint(ItemStack stack) {
return !isChargable() || stack.hasEnchantments() || ChargeableItem.getEnergy(stack) > 0; return stack.hasEnchantments() || Charges.of(stack).maximum() == 0 || Charges.of(stack).energy() > 0;
} }
public boolean isApplicable(ItemStack stack) { public boolean isApplicable(ItemStack stack) {
return stack.getItem() == this && (!isChargable() || ChargeableItem.getEnergy(stack) > 0); return stack.getItem() == this && (Charges.of(stack).maximum() == 0 || Charges.of(stack).energy() > 0);
} }
public final boolean isApplicable(LivingEntity entity) { public final boolean isApplicable(LivingEntity entity) {
@ -83,11 +84,6 @@ public class AmuletItem extends WearableItem implements ChargeableItem {
.orElse(TrinketsDelegate.EquippedStack.EMPTY); .orElse(TrinketsDelegate.EquippedStack.EMPTY);
} }
@Override
public int getMaxCharge() {
return maxEnergy;
}
public static TrinketsDelegate.EquippedStack get(LivingEntity entity) { public static TrinketsDelegate.EquippedStack get(LivingEntity entity) {
return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE, stack -> stack.getItem() instanceof AmuletItem) return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE, stack -> stack.getItem() instanceof AmuletItem)
.findFirst() .findFirst()

View file

@ -7,6 +7,8 @@ import com.minelittlepony.unicopia.entity.Creature;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
@ -31,9 +33,9 @@ import net.minecraft.util.UseAction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public class BellItem extends Item implements ChargeableItem { public class BellItem extends Item {
public BellItem(Settings settings) { public BellItem(Settings settings) {
super(settings); super(settings.component(UDataComponentTypes.CHARGES, Charges.of(1000, 1000)));
} }
@Override @Override
@ -43,7 +45,7 @@ public class BellItem extends Item implements ChargeableItem {
@Override @Override
public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> list, TooltipType type) { public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> list, TooltipType type) {
list.add(Text.translatable(getTranslationKey() + ".charges", (int)Math.floor(ChargeableItem.getEnergy(stack)), getMaxCharge())); Charges.of(stack).appendTooltip(context, list::add, type);
} }
@Override @Override
@ -69,23 +71,28 @@ public class BellItem extends Item implements ChargeableItem {
ItemStack stack = player.getStackInHand(hand); ItemStack stack = player.getStackInHand(hand);
ItemStack offhandStack = AmuletItem.get(player).stack(); ItemStack offhandStack = AmuletItem.get(player).stack();
if (!(offhandStack.getItem() instanceof ChargeableItem)) { if (!Charges.of(offhandStack).canHoldCharge()) {
offhandStack = player.getStackInHand(hand == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND); offhandStack = player.getStackInHand(hand == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND);
} }
Pony pony = Pony.of(player); Pony pony = Pony.of(player);
if (hasCharge(stack)) { Charges charges = Charges.of(stack);
if (charges.energy() > 0) {
pony.playSound(USounds.ITEM_GROGAR_BELL_CHARGE, 0.6F, 1); pony.playSound(USounds.ITEM_GROGAR_BELL_CHARGE, 0.6F, 1);
pony.getCorruption().add(player.getRandom().nextBetween(1, 10)); pony.getCorruption().add(player.getRandom().nextBetween(1, 10));
if (offhandStack.getItem() instanceof ChargeableItem chargeable) {
float maxChargeBy = chargeable.getMaxCharge() - ChargeableItem.getEnergy(offhandStack); Charges offhandCharges = Charges.of(offhandStack);
float energyTransferred = Math.min(ChargeableItem.getEnergy(stack), maxChargeBy);
chargeable.recharge(offhandStack, energyTransferred); if (offhandCharges.canHoldCharge()) {
ChargeableItem.consumeEnergy(stack, energyTransferred); int maxChargeBy = charges.maximum() - offhandCharges.energy();
int energyTransferred = Math.min(charges.energy(), maxChargeBy);
Charges.recharge(offhandStack, energyTransferred);
Charges.discharge(stack, energyTransferred);
} else { } else {
pony.getMagicalReserves().getMana().add(ChargeableItem.getEnergy(stack)); pony.getMagicalReserves().getMana().add(charges.energy());
ChargeableItem.setEnergy(stack, 0); stack.set(UDataComponentTypes.CHARGES, charges.withEnergy(0));
} }
pony.spawnParticles(pony.getPhysics().getHeadPosition().toCenterPos(), new Sphere(false, 0.5F), 7, p -> { pony.spawnParticles(pony.getPhysics().getHeadPosition().toCenterPos(), new Sphere(false, 0.5F), 7, p -> {
@ -166,18 +173,18 @@ public class BellItem extends Item implements ChargeableItem {
return true; return true;
} }
} }
ChargeableItem.consumeEnergy(stack, -amountDrawn); if (Charges.discharge(stack, -(int)amountDrawn)) {
user.playSound(USounds.ITEM_GROGAR_BELL_DRAIN, 0.2F, progress);
user.playSound(USounds.ITEM_GROGAR_BELL_DRAIN, 0.2F, progress); for (int i = 0; i < 4; i++) {
living.addParticle(
for (int i = 0; i < 4; i++) { new FollowingParticleEffect(UParticles.HEALTH_DRAIN, user.asEntity(), 0.4F)
living.addParticle( .withChild(particleType),
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, user.asEntity(), 0.4F) living.getOriginVector().add(0, living.getPhysics().getGravitySignum() * living.asEntity().getHeight() / 2, 0)
.withChild(particleType), .add(VecHelper.supply(() -> user.asWorld().random.nextTriangular(0, 0.2))),
living.getOriginVector().add(0, living.getPhysics().getGravitySignum() * living.asEntity().getHeight() / 2, 0) Vec3d.ZERO
.add(VecHelper.supply(() -> user.asWorld().random.nextTriangular(0, 0.2))), );
Vec3d.ZERO }
);
} }
return false; return false;
@ -204,11 +211,6 @@ public class BellItem extends Item implements ChargeableItem {
@Override @Override
public boolean hasGlint(ItemStack stack) { public boolean hasGlint(ItemStack stack) {
return stack.hasEnchantments() || ChargeableItem.getEnergy(stack) > 0; return super.hasGlint(stack) || Charges.of(stack).energy() > 0;
}
@Override
public int getMaxCharge() {
return 1000;
} }
} }

View file

@ -1,58 +0,0 @@
package com.minelittlepony.unicopia.item;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.Identifier;
import net.minecraft.registry.Registries;
public interface ChameleonItem {
default boolean isFullyDisguised() {
return true;
}
static ItemStack getAppearanceStack(ItemStack stack) {
Item appearance = getAppearance(stack);
if (appearance != Items.AIR) {
return createAppearanceStack(stack, appearance);
}
return stack;
}
static ItemStack createAppearanceStack(ItemStack stack, Item appearance) {
ItemStack newAppearance = appearance.getDefaultStack();
if (stack.hasNbt()) {
newAppearance.setNbt(stack.getNbt().copy());
}
newAppearance.setCount(stack.getCount());
newAppearance.removeSubNbt("appearance");
return newAppearance;
}
static boolean hasAppearance(ItemStack stack) {
return getAppearance(stack) != Items.AIR;
}
static Item getAppearance(ItemStack stack) {
if (stack.hasNbt() && stack.getNbt().contains("appearance")) {
return Registries.ITEM.get(new Identifier(stack.getNbt().getString("appearance")));
}
return Items.AIR;
}
static ItemStack setAppearance(ItemStack stack, ItemStack appearance) {
ItemStack result = stack.copy();
if (appearance.hasNbt()) {
result.setNbt(appearance.getNbt().copy());
result.removeCustomName();
result.setDamage(stack.getDamage());
result.setCount(stack.getCount());
}
result.getOrCreateNbt().putString("appearance", Registries.ITEM.getId(appearance.getItem()).toString());
return result;
}
}

View file

@ -1,64 +0,0 @@
package com.minelittlepony.unicopia.item;
import net.minecraft.item.ItemStack;
public interface ChargeableItem {
int getMaxCharge();
default int getDefaultCharge() {
return 0;
}
default boolean isChargable() {
return getMaxCharge() > 0;
}
default boolean hasCharge(ItemStack stack) {
return getEnergy(stack) > 0;
}
default ItemStack recharge(ItemStack stack) {
return setEnergy(stack, getMaxCharge());
}
default ItemStack recharge(ItemStack stack, float amount) {
return setEnergy(stack, getEnergy(stack) + amount);
}
default boolean canCharge(ItemStack stack) {
return isChargable() && getEnergy(stack) < getMaxCharge();
}
default float getChargeRemainder(ItemStack stack) {
return Math.max(0, getMaxCharge() - getEnergy(stack));
}
default void onDischarge(ItemStack stack) {
}
static void consumeEnergy(ItemStack stack, float amount) {
setEnergy(stack, getEnergy(stack) - amount);
if (stack.getItem() instanceof ChargeableItem c) {
c.onDischarge(stack);
}
}
static int getDefaultCharge(ItemStack stack) {
return stack.getItem() instanceof ChargeableItem c ? c.getDefaultCharge() : 0;
}
static float getEnergy(ItemStack stack) {
return stack.hasNbt() && stack.getNbt().contains("energy") ? Math.max(0, stack.getNbt().getFloat("energy")) : getDefaultCharge(stack);
}
static ItemStack setEnergy(ItemStack stack, float energy) {
if (energy <= 0 && getDefaultCharge(stack) <= 0) {
stack.removeSubNbt("energy");
} else {
stack.getOrCreateNbt().putFloat("energy", energy);
}
return stack;
}
}

View file

@ -0,0 +1,7 @@
package com.minelittlepony.unicopia.item;
import net.minecraft.entity.damage.DamageSource;
public interface DamageChecker {
boolean takesDamageFrom(DamageSource source);
}

View file

@ -15,6 +15,8 @@ import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import com.minelittlepony.unicopia.item.group.MultiItem; import com.minelittlepony.unicopia.item.group.MultiItem;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -34,9 +36,9 @@ import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public class EnchantedStaffItem extends StaffItem implements EnchantableItem, ChargeableItem, MultiItem { public class EnchantedStaffItem extends StaffItem implements EnchantableItem, MultiItem, Charges.ChargeChangeCallback {
private static final Map<EntityType<?>, SpellType<?>> ENTITY_TYPE_TO_SPELL = new HashMap<>(); private static final Map<EntityType<?>, SpellType<?>> ENTITY_TYPE_TO_SPELL = new HashMap<>();
public static <T extends Spell> SpellType<T> register(EntityType<?> entityType, SpellType<T> spellType) { public static <T extends Spell> SpellType<T> register(EntityType<?> entityType, SpellType<T> spellType) {
ENTITY_TYPE_TO_SPELL.put(entityType, spellType); ENTITY_TYPE_TO_SPELL.put(entityType, spellType);
return spellType; return spellType;
@ -83,7 +85,7 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
} }
public EnchantedStaffItem(Settings settings) { public EnchantedStaffItem(Settings settings) {
super(settings.maxDamage(500)); super(settings.component(UDataComponentTypes.CHARGES, new Charges(3, 3, 3, true)).maxDamage(500));
} }
@Override @Override
@ -96,12 +98,11 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
@Override @Override
public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> lines, TooltipType type) { public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> lines, TooltipType type) {
if (EnchantableItem.isEnchanted(stack)) { if (EnchantableItem.isEnchanted(stack)) {
SpellType<?> key = EnchantableItem.getSpellKey(stack); SpellType<?> key = EnchantableItem.getSpellKey(stack);
lines.add(Text.translatable(key.getTranslationKey()).formatted(key.getAffinity().getColor())); lines.add(Text.translatable(key.getTranslationKey()).formatted(key.getAffinity().getColor()));
lines.add(Text.translatable(getTranslationKey(stack) + ".charges", (int)Math.floor(ChargeableItem.getEnergy(stack)), getMaxCharge()));
} }
Charges.of(stack).appendTooltip(context, lines::add, type);
} }
@Override @Override
@ -119,7 +120,9 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
target.setHealth(1); target.setHealth(1);
target.setFrozenTicks(9000); target.setFrozenTicks(9000);
} }
player.setStackInHand(hand, recharge(EnchantableItem.enchant(stack, type))); stack = EnchantableItem.enchant(stack, type);
Charges.recharge(stack);
player.setStackInHand(hand, stack);
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} }
@ -135,36 +138,35 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
public void onStoppedUsing(ItemStack stack, World world, LivingEntity entity, int timeLeft) { public void onStoppedUsing(ItemStack stack, World world, LivingEntity entity, int timeLeft) {
int i = getMaxUseTime(stack, entity) - timeLeft; int i = getMaxUseTime(stack, entity) - timeLeft;
if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) { if (EnchantableItem.isEnchanted(stack)) {
if (i > 20) { if (i > 20) {
Pony.of(entity).ifPresent(pony -> { if (Charges.discharge(stack, 1)) {
pony.subtractEnergyCost(4); Pony.of(entity).ifPresent(pony -> {
stack.damage(1, pony.asEntity(), EquipmentSlot.MAINHAND); pony.subtractEnergyCost(4);
getSpellEffect(stack).create().toThrowable().throwProjectile(pony); stack.damage(1, pony.asEntity(), EquipmentSlot.MAINHAND);
pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10); getSpellEffect(stack).create().toThrowable().throwProjectile(pony);
}); pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10);
ChargeableItem.consumeEnergy(stack, 1); });
}
} else if (i > 5) { } else if (i > 5) {
Pony.of(entity).ifPresent(pony -> { if (Charges.discharge(stack, 1)) {
pony.subtractEnergyCost(4); Pony.of(entity).ifPresent(pony -> {
stack.damage(1, pony.asEntity(), EquipmentSlot.MAINHAND); pony.subtractEnergyCost(4);
getSpellEffect(stack).create().toThrowable().throwProjectile(pony); stack.damage(1, pony.asEntity(), EquipmentSlot.MAINHAND);
pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10); getSpellEffect(stack).create().toThrowable().throwProjectile(pony);
}); pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10);
ChargeableItem.consumeEnergy(stack, 1); });
}
} }
} }
} }
@Override @Override
protected boolean castContainedEffect(ItemStack stack, LivingEntity target, LivingEntity attacker) { protected boolean castContainedEffect(ItemStack stack, LivingEntity target, LivingEntity attacker) {
if (attacker.isSneaking() && hasCharge(stack)) { if (attacker.isSneaking() && Charges.discharge(stack, 1)) {
stack.damage(50, attacker, EquipmentSlot.MAINHAND); stack.damage(50, attacker, EquipmentSlot.MAINHAND);
Caster.of(attacker).ifPresent(c -> c.subtractEnergyCost(4)); Caster.of(attacker).ifPresent(c -> c.subtractEnergyCost(4));
Caster.of(target).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF)); Caster.of(target).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF));
ChargeableItem.consumeEnergy(stack, 1);
return true;
} }
return false; return false;
@ -190,9 +192,8 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
if (i > 200) { if (i > 200) {
living.clearActiveItem(); living.clearActiveItem();
living.damage(entity.getDamageSources().magic(), 1); living.damage(entity.getDamageSources().magic(), 1);
if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) { if (EnchantableItem.isEnchanted(stack) && Charges.discharge(stack, 1)) {
Caster.of(entity).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF)); Caster.of(entity).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF));
ChargeableItem.consumeEnergy(stack, 1);
} }
} }
} }
@ -204,19 +205,9 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
return 72000; return 72000;
} }
@Override
public int getMaxCharge() {
return 3;
}
@Override
public int getDefaultCharge() {
return 3;
}
@Override @Override
public Text getName(ItemStack stack) { public Text getName(ItemStack stack) {
if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) { if (EnchantableItem.isEnchanted(stack) && Charges.of(stack).energy() > 0) {
return Text.translatable(this.getTranslationKey(stack) + ".enchanted", super.getName(stack), EnchantableItem.getSpellKey(stack).getName()); return Text.translatable(this.getTranslationKey(stack) + ".enchanted", super.getName(stack), EnchantableItem.getSpellKey(stack).getName());
} }
return super.getName(stack); return super.getName(stack);
@ -224,7 +215,7 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
@Override @Override
public void onDischarge(ItemStack stack) { public void onDischarge(ItemStack stack) {
if (ChargeableItem.getEnergy(stack) == 0) { if (Charges.of(stack).energy() == 0) {
EnchantableItem.unenchant(stack); EnchantableItem.unenchant(stack);
} }
} }

View file

@ -3,6 +3,8 @@ package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.mob.ButterflyEntity; import com.minelittlepony.unicopia.entity.mob.ButterflyEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.item.component.Appearance;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
@ -22,7 +24,7 @@ import net.minecraft.text.Text;
import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.world.WorldEvents; import net.minecraft.world.WorldEvents;
public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.HitListener, ChameleonItem { public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.HitListener {
public FilledJarItem(Item.Settings settings) { public FilledJarItem(Item.Settings settings) {
super(settings, 0); super(settings, 0);
} }
@ -34,12 +36,8 @@ public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.
@Override @Override
public Text getName(ItemStack stack) { public Text getName(ItemStack stack) {
return ChameleonItem.hasAppearance(stack) ? Text.translatable(getTranslationKey(stack), ChameleonItem.getAppearanceStack(stack).getName()) : UItems.EMPTY_JAR.getName(UItems.EMPTY_JAR.getDefaultStack()); Appearance appearance = stack.get(UDataComponentTypes.APPEARANCE);
} return appearance != null ? Text.translatable(getTranslationKey(stack), appearance.item().getName()) : UItems.EMPTY_JAR.getName(UItems.EMPTY_JAR.getDefaultStack());
@Override
public boolean isFullyDisguised() {
return false;
} }
@Override @Override
@ -50,7 +48,7 @@ public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.
return; return;
} }
ItemStack stack = ChameleonItem.getAppearanceStack(((FlyingItemEntity)projectile).getStack()); ItemStack stack = Appearance.upwrapAppearance(((FlyingItemEntity)projectile).getStack());
boolean onFire = false; boolean onFire = false;
@ -81,7 +79,7 @@ public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.
@Override @Override
public void onImpact(MagicProjectileEntity projectile) { public void onImpact(MagicProjectileEntity projectile) {
ItemStack stack = ChameleonItem.getAppearanceStack(projectile.getStack()); ItemStack stack = Appearance.upwrapAppearance(projectile.getStack());
if (stack.isOf(UItems.BUTTERFLY)) { if (stack.isOf(UItems.BUTTERFLY)) {
ButterflyEntity butterfly = UEntities.BUTTERFLY.create(projectile.getWorld()); ButterflyEntity butterfly = UEntities.BUTTERFLY.create(projectile.getWorld());
@ -98,6 +96,6 @@ public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.
} }
public ItemStack withContents(ItemStack contents) { public ItemStack withContents(ItemStack contents) {
return ChameleonItem.setAppearance(getDefaultStack(), contents); return Appearance.set(getDefaultStack(), contents);
} }
} }

View file

@ -1,7 +1,7 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.ItemTracker; import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import net.minecraft.entity.*; import net.minecraft.entity.*;
@ -10,24 +10,9 @@ import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.world.World; import net.minecraft.world.World;
public class PegasusAmuletItem extends AmuletItem implements ItemTracker.Trackable { public class PegasusAmuletItem extends AmuletItem {
public PegasusAmuletItem(Item.Settings settings, int maxEnergy) { public PegasusAmuletItem(Item.Settings settings, int maxEnergy) {
super(settings, maxEnergy); super(settings.component(UDataComponentTypes.CHARGES, Charges.of(maxEnergy / 2, maxEnergy)));
}
@Override
public void onUnequipped(Living<?> living, long timeWorn) {
}
@Override
public void onEquipped(Living<?> living) {
}
@Override
public int getDefaultCharge() {
return getMaxCharge() / 2;
} }
@Override @Override

View file

@ -8,12 +8,15 @@ import com.minelittlepony.unicopia.advancement.UCriteria;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.component.Appearance;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import com.minelittlepony.unicopia.item.group.MultiItem; import com.minelittlepony.unicopia.item.group.MultiItem;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.util.TraceHelper; import com.minelittlepony.unicopia.util.TraceHelper;
import com.minelittlepony.unicopia.util.RegistryUtils; import com.minelittlepony.unicopia.util.RegistryUtils;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LightningEntity;
@ -31,13 +34,12 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.Rarity; import net.minecraft.util.Rarity;
import net.minecraft.util.TypedActionResult; import net.minecraft.util.TypedActionResult;
import net.minecraft.registry.Registries;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent; import net.minecraft.world.event.GameEvent;
public class ZapAppleItem extends Item implements ChameleonItem, MultiItem { public class ZapAppleItem extends Item implements MultiItem, Appearance.AppearanceChangeCallback {
public ZapAppleItem(Settings settings) { public ZapAppleItem(Settings settings) {
super(settings.rarity(Rarity.RARE)); super(settings.rarity(Rarity.RARE).component(UDataComponentTypes.APPEARANCE, Appearance.DEFAULT_FULLY_DISGUISED));
} }
@Override @Override
@ -105,21 +107,18 @@ public class ZapAppleItem extends Item implements ChameleonItem, MultiItem {
.stream() .stream()
.flatMap(world -> RegistryUtils.valuesForTag(world, UConventionalTags.Items.APPLES)) .flatMap(world -> RegistryUtils.valuesForTag(world, UConventionalTags.Items.APPLES))
.filter(a -> a != this).map(item -> { .filter(a -> a != this).map(item -> {
return ChameleonItem.setAppearance(getDefaultStack(), item.getDefaultStack()); return Appearance.set(getDefaultStack(), item.getDefaultStack());
}).toList(); }).toList();
} }
@Override @Override
public Text getName(ItemStack stack) { public Text getName(ItemStack stack) {
return ChameleonItem.hasAppearance(stack) ? ChameleonItem.getAppearanceStack(stack).getName() : super.getName(stack); Appearance appearance = stack.get(UDataComponentTypes.APPEARANCE);
return appearance != null ? appearance.item().getName() : super.getName(stack);
} }
@Override @Override
public Rarity getRarity(ItemStack stack) { public void onAppearanceSet(ItemStack stack, Appearance appearance) {
if (ChameleonItem.hasAppearance(stack)) { stack.set(DataComponentTypes.RARITY, appearance.item().isEmpty() ? stack.getDefaultComponents().get(DataComponentTypes.RARITY) : Rarity.EPIC);
return Rarity.EPIC;
}
return Rarity.RARE;
} }
} }

View file

@ -0,0 +1,77 @@
package com.minelittlepony.unicopia.item.component;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.registry.Registries;
public record Appearance(ItemStack item, boolean replaceFully) {
public static final Appearance DEFAULT = new Appearance(ItemStack.EMPTY, false);
public static final Appearance DEFAULT_FULLY_DISGUISED = new Appearance(ItemStack.EMPTY, true);
public static final Codec<Appearance> CODEC = RecordCodecBuilder.create(instance -> instance.group(
CodecUtils.xor(
ItemStack.CODEC,
Registries.ITEM.getCodec().xmap(Item::getDefaultStack, ItemStack::getItem)
).fieldOf("stack").forGetter(Appearance::item),
Codec.BOOL.fieldOf("replace_fully").forGetter(Appearance::replaceFully)
).apply(instance, Appearance::of));
public static final PacketCodec<RegistryByteBuf, Appearance> PACKET_CODEC = PacketCodec.tuple(
ItemStack.PACKET_CODEC, Appearance::item,
PacketCodecs.BOOL, Appearance::replaceFully,
Appearance::of
);
public Appearance {
item.remove(UDataComponentTypes.APPEARANCE);
}
public ItemStack unwrap(ItemStack stack) {
return item().isEmpty() ? stack : item();
}
public static Appearance of(ItemStack stack, boolean complete) {
return stack.isEmpty() ? (complete ? DEFAULT_FULLY_DISGUISED : DEFAULT) : new Appearance(stack, complete);
}
public static Appearance get(ItemStack stack) {
return stack.getOrDefault(UDataComponentTypes.APPEARANCE, DEFAULT);
}
public static boolean hasAppearance(ItemStack stack) {
return !get(stack).item().isEmpty();
}
public static ItemStack upwrapAppearance(ItemStack stack) {
return get(stack).unwrap(stack);
}
public static ItemStack set(ItemStack stack, ItemStack appearance) {
Appearance component = createAppearanceFor(stack, appearance);
stack.set(UDataComponentTypes.APPEARANCE, component);
if (stack.getItem() instanceof AppearanceChangeCallback callback) {
callback.onAppearanceSet(stack, component);
}
return stack;
}
private static Appearance createAppearanceFor(ItemStack stack, ItemStack appearance) {
if (appearance.isEmpty()) {
return stack.getDefaultComponents().getOrDefault(UDataComponentTypes.APPEARANCE, DEFAULT);
}
appearance = appearance.copy();
appearance.setCount(stack.getCount());
appearance.setDamage(stack.getDamage());
return of(appearance, stack.getOrDefault(UDataComponentTypes.APPEARANCE, DEFAULT).replaceFully());
}
public interface AppearanceChangeCallback {
void onAppearanceSet(ItemStack stack, Appearance appearance);
}
}

View file

@ -0,0 +1,99 @@
package com.minelittlepony.unicopia.item.component;
import java.util.function.Consumer;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.netty.buffer.ByteBuf;
import net.minecraft.item.Item.TooltipContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipAppender;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
public record Charges(int energy, int maximum, int baseline, boolean showInTooltip) implements TooltipAppender {
public static final Charges DEFAULT = new Charges(0, 0, 0, false);
public static final Codec<Charges> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("energy").forGetter(Charges::energy),
Codec.INT.optionalFieldOf("maximum", 0).forGetter(Charges::maximum),
Codec.INT.optionalFieldOf("baseline", 0).forGetter(Charges::baseline),
Codec.BOOL.fieldOf("showInTooltip").forGetter(Charges::showInTooltip)
).apply(instance, Charges::new));
public static final PacketCodec<ByteBuf, Charges> PACKET_CODEC = PacketCodec.tuple(
PacketCodecs.INTEGER, Charges::energy,
PacketCodecs.INTEGER, Charges::maximum,
PacketCodecs.INTEGER, Charges::baseline,
PacketCodecs.BOOL, Charges::showInTooltip,
Charges::new
);
public static Charges of(int initial, int maximum) {
return new Charges(initial, maximum, initial, true);
}
public static Charges of(ItemStack stack) {
return stack.getOrDefault(UDataComponentTypes.CHARGES, DEFAULT);
}
public static boolean discharge(ItemStack stack, int energy) {
Charges charges = of(stack);
if (charges.energy() < energy) {
return false;
}
stack.set(UDataComponentTypes.CHARGES, charges.withEnergy(charges.energy() - energy));
if (stack.getItem() instanceof ChargeChangeCallback callback) {
callback.onDischarge(stack);
}
return true;
}
public static boolean recharge(ItemStack stack, int energy) {
Charges charges = of(stack);
if (charges.energy() >= charges.maximum()) {
return false;
}
stack.set(UDataComponentTypes.CHARGES, charges.withEnergy(charges.energy() + energy));
return true;
}
public static boolean recharge(ItemStack stack) {
Charges charges = of(stack);
if (charges.energy() >= charges.maximum()) {
return false;
}
stack.set(UDataComponentTypes.CHARGES, charges.ofDefault());
return true;
}
public boolean canHoldCharge() {
return maximum > 0;
}
public float getPercentage() {
return canHoldCharge() ? energy() / (float)maximum() : 0;
}
public Charges withEnergy(int energy) {
return new Charges(MathHelper.clamp(energy, 0, maximum), maximum, baseline, showInTooltip);
}
public Charges ofDefault() {
return withEnergy(baseline);
}
@Override
public void appendTooltip(TooltipContext context, Consumer<Text> tooltip, TooltipType type) {
if (showInTooltip() && maximum() > 0) {
tooltip.accept(Text.translatable("item.unicopia.amulet.energy", (int)Math.floor(energy()), maximum()));
}
}
public interface ChargeChangeCallback {
void onDischarge(ItemStack stack);
}
}

View file

@ -23,6 +23,8 @@ public interface UDataComponentTypes {
ComponentType<ButterflyEntity.Variant> BUTTERFLY_VARIANT = register("butterfly_variant", builder -> builder.codec(ButterflyEntity.Variant.CODEC).packetCodec(ButterflyEntity.Variant.PACKET_CODEC)); ComponentType<ButterflyEntity.Variant> BUTTERFLY_VARIANT = register("butterfly_variant", builder -> builder.codec(ButterflyEntity.Variant.CODEC).packetCodec(ButterflyEntity.Variant.PACKET_CODEC));
ComponentType<AirBalloonEntity.BalloonDesign> BALLOON_DESIGN = register("balloon_design", builder -> builder.codec(AirBalloonEntity.BalloonDesign.CODEC).packetCodec(AirBalloonEntity.BalloonDesign.PACKET_CODEC)); ComponentType<AirBalloonEntity.BalloonDesign> BALLOON_DESIGN = register("balloon_design", builder -> builder.codec(AirBalloonEntity.BalloonDesign.CODEC).packetCodec(AirBalloonEntity.BalloonDesign.PACKET_CODEC));
ComponentType<Issuer> ISSUER = register("issuer", builder -> builder.codec(Issuer.CODEC).packetCodec(Issuer.PACKET_CODEC).cache()); ComponentType<Issuer> ISSUER = register("issuer", builder -> builder.codec(Issuer.CODEC).packetCodec(Issuer.PACKET_CODEC).cache());
ComponentType<Charges> CHARGES = register("charges", builder -> builder.codec(Charges.CODEC).packetCodec(Charges.PACKET_CODEC));
ComponentType<Appearance> APPEARANCE = register("appearance", builder -> builder.codec(Appearance.CODEC).packetCodec(Appearance.PACKET_CODEC));
private static <T> ComponentType<T> register(String name, UnaryOperator<ComponentType.Builder<T>> builderOperator) { private static <T> ComponentType<T> register(String name, UnaryOperator<ComponentType.Builder<T>> builderOperator) {
return Registry.register(Registries.DATA_COMPONENT_TYPE, Unicopia.id(name), builderOperator.apply(ComponentType.builder()).build()); return Registry.register(Registries.DATA_COMPONENT_TYPE, Unicopia.id(name), builderOperator.apply(ComponentType.builder()).build());

View file

@ -5,8 +5,6 @@ import com.minelittlepony.unicopia.client.sound.MagicAuraSoundInstance;
import com.minelittlepony.unicopia.entity.Enchantments; import com.minelittlepony.unicopia.entity.Enchantments;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;

View file

@ -3,15 +3,17 @@ package com.minelittlepony.unicopia.item.group;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Appearance;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import net.minecraft.item.*; import net.minecraft.item.*;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
public interface UItemGroups { public interface UItemGroups {
RegistryKey<ItemGroup> ALL_ITEMS = ItemGroupRegistry.createDynamic("items", UItems.CRYSTAL_HEART::getDefaultStack, () -> { RegistryKey<ItemGroup> ALL_ITEMS = ItemGroupRegistry.createDynamic("items", UItems.CRYSTAL_HEART::getDefaultStack, () -> {
return Stream.concat(Stream.of(Items.APPLE), ItemGroupRegistry.ITEMS.stream() return Stream.concat(Stream.of(Items.APPLE), ItemGroupRegistry.ITEMS.stream()
.filter(item -> !(item instanceof ChameleonItem) || ((ChameleonItem)item).isFullyDisguised())); .filter(item -> !item.getComponents().getOrDefault(UDataComponentTypes.APPEARANCE, Appearance.DEFAULT).replaceFully()));
}); });
RegistryKey<ItemGroup> FORAGING_ITEMS = ItemGroupRegistry.createGroupFromTag("foraging", UTags.Items.GROUP_FORAGING, Items.HAY_BLOCK::getDefaultStack); RegistryKey<ItemGroup> FORAGING_ITEMS = ItemGroupRegistry.createGroupFromTag("foraging", UTags.Items.GROUP_FORAGING, Items.HAY_BLOCK::getDefaultStack);
RegistryKey<ItemGroup> EARTH_PONY_ITEMS = ItemGroupRegistry.createGroupFromTag("earth_pony", UTags.Items.GROUP_EARTH_PONY, UItems.EARTH_BADGE::getDefaultStack); RegistryKey<ItemGroup> EARTH_PONY_ITEMS = ItemGroupRegistry.createGroupFromTag("earth_pony", UTags.Items.GROUP_EARTH_PONY, UItems.EARTH_BADGE::getDefaultStack);

View file

@ -6,7 +6,10 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.diet.DietView; import com.minelittlepony.unicopia.diet.DietView;
import com.minelittlepony.unicopia.item.DamageChecker;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
@ -30,4 +33,12 @@ abstract class MixinItemStack {
ItemStack self = (ItemStack)(Object)this; ItemStack self = (ItemStack)(Object)this;
((DietView.Holder)self.getItem()).getDiets(self).finishUsing(self, world, user); ((DietView.Holder)self.getItem()).getDiets(self).finishUsing(self, world, user);
} }
@Inject(method = "takesDamageFrom", at = @At("HEAD"))
private void onTakesDamageFrom(DamageSource source, CallbackInfoReturnable<Boolean> info) {
ItemStack self = (ItemStack)(Object)this;
if (self.getItem() instanceof DamageChecker checker) {
info.setReturnValue(checker.takesDamageFrom(source));
}
}
} }

View file

@ -4,7 +4,9 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.ModifyVariable;
import com.minelittlepony.unicopia.item.ChameleonItem; import com.minelittlepony.unicopia.item.component.Appearance;
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
import net.minecraft.client.render.item.ItemModels; import net.minecraft.client.render.item.ItemModels;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -14,8 +16,9 @@ abstract class MixinItemModels {
at = @At("HEAD"), at = @At("HEAD"),
index = 1) index = 1)
private ItemStack modifyStack(ItemStack stack) { private ItemStack modifyStack(ItemStack stack) {
if (stack.getItem() instanceof ChameleonItem && ((ChameleonItem)stack.getItem()).isFullyDisguised()) { Appearance appearance = stack.get(UDataComponentTypes.APPEARANCE);
return ChameleonItem.getAppearanceStack(stack); if (appearance != null && appearance.replaceFully()) {
return Appearance.upwrapAppearance(stack);
} }
return stack; return stack;
} }

View file

@ -9,7 +9,6 @@ import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
import net.minecraft.entity.player.BlockBreakingInfo; import net.minecraft.entity.player.BlockBreakingInfo;
@Pseudo @Pseudo

View file

@ -2,8 +2,8 @@ package com.minelittlepony.unicopia.recipe;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Appearance;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.RecipeSerializer;
@ -45,14 +45,14 @@ public class JarExtractRecipe extends SpecialCraftingRecipe {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
if (!ChameleonItem.hasAppearance(stack)) { if (!Appearance.hasAppearance(stack)) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
jar = stack; jar = stack;
} }
return ChameleonItem.getAppearanceStack(jar); return Appearance.upwrapAppearance(jar);
} }
@Override @Override

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.recipe; package com.minelittlepony.unicopia.recipe;
import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.EmptyJarItem; import com.minelittlepony.unicopia.item.EmptyJarItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Appearance;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.RecipeSerializer;
@ -19,7 +19,7 @@ public class JarInsertRecipe extends ItemCombinationRecipe {
@Override @Override
public final ItemStack craft(CraftingRecipeInput inventory, WrapperLookup registries) { public final ItemStack craft(CraftingRecipeInput inventory, WrapperLookup registries) {
return ChameleonItem.setAppearance(UItems.FILLED_JAR.getDefaultStack(), runMatch(inventory).getRight()); return Appearance.set(UItems.FILLED_JAR.getDefaultStack(), runMatch(inventory).getRight());
} }
@Override @Override

View file

@ -3,8 +3,8 @@ package com.minelittlepony.unicopia.recipe;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Appearance;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.RegistryByteBuf;
@ -21,8 +21,8 @@ public class ZapAppleRecipe extends ShapelessRecipe {
Codec.STRING.optionalFieldOf("group", "").forGetter(ZapAppleRecipe::getGroup), Codec.STRING.optionalFieldOf("group", "").forGetter(ZapAppleRecipe::getGroup),
CraftingRecipeCategory.CODEC.optionalFieldOf("category", CraftingRecipeCategory.MISC).forGetter(ZapAppleRecipe::getCategory), CraftingRecipeCategory.CODEC.optionalFieldOf("category", CraftingRecipeCategory.MISC).forGetter(ZapAppleRecipe::getCategory),
Registries.ITEM.getCodec().xmap( Registries.ITEM.getCodec().xmap(
item -> ChameleonItem.setAppearance(UItems.ZAP_APPLE.getDefaultStack(), item.getDefaultStack()), item -> Appearance.set(UItems.ZAP_APPLE.getDefaultStack(), item.getDefaultStack()),
stack -> ChameleonItem.getAppearance(stack) stack -> Appearance.upwrapAppearance(stack).getItem()
).fieldOf("appearance").forGetter(recipe -> recipe.getResult(null)), ).fieldOf("appearance").forGetter(recipe -> recipe.getResult(null)),
URecipes.SHAPELESS_RECIPE_INGREDIENTS_CODEC.fieldOf("ingredients").forGetter(ZapAppleRecipe::getIngredients) URecipes.SHAPELESS_RECIPE_INGREDIENTS_CODEC.fieldOf("ingredients").forGetter(ZapAppleRecipe::getIngredients)
).apply(instance, ZapAppleRecipe::new)); ).apply(instance, ZapAppleRecipe::new));

View file

@ -70,9 +70,4 @@ public interface ColorHelper {
return Argb.fromFloats(a, r, g, b); return Argb.fromFloats(a, r, g, b);
} }
@Deprecated
static int lerp(float delta, int fromColor, int toColor) {
return Argb.lerp(delta, fromColor, toColor);
}
} }

View file

@ -8,11 +8,10 @@ import java.util.function.Supplier;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.component.ComponentType;
import net.minecraft.fluid.FluidState; import net.minecraft.fluid.FluidState;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
final class PsyFluidHelper { final class PsyFluidHelper {
private static final Supplier<Optional<Class<?>>> SIMPLE_FLUID_CLASS = Suppliers.memoize(() -> { private static final Supplier<Optional<Class<?>>> SIMPLE_FLUID_CLASS = Suppliers.memoize(() -> {
@ -22,24 +21,37 @@ final class PsyFluidHelper {
return Optional.empty(); return Optional.empty();
} }
}); });
private static final Supplier<Optional<Class<?>>> ITEM_FLUIDS_CLASS = Suppliers.memoize(() -> {
try {
return Optional.ofNullable(Class.forName("ivorius.psychedelicraft.item.component.ItemFluids"));
} catch (Throwable t) {
return Optional.empty();
}
});
private static final Function<FluidVariant, FluidState> FALLBACK_METHOD = fluid -> fluid.getFluid().getDefaultState(); private static final Function<FluidVariant, FluidState> FALLBACK_METHOD = fluid -> fluid.getFluid().getDefaultState();
private static final Supplier<Function<FluidVariant, FluidState>> GET_FULL_FLUID_STATE = Suppliers.memoize(() -> SIMPLE_FLUID_CLASS.get().<Function<FluidVariant, FluidState>>map(type -> { private static final Supplier<Function<FluidVariant, FluidState>> GET_FULL_FLUID_STATE = Suppliers.memoize(
try { () -> SIMPLE_FLUID_CLASS.get().<Function<FluidVariant, FluidState>>map(type -> {
final Method method = type.getDeclaredMethod("getFluidState", ItemStack.class); return ITEM_FLUIDS_CLASS.get().<Function<FluidVariant, FluidState>>map(fluidsType -> {
if (method != null) { try {
return fluid -> { ComponentType<?> fluidsComponentType = Registries.DATA_COMPONENT_TYPE.get(Identifier.of("psychedelicraft", "fluids"));
try { if (fluidsComponentType != null) {
ItemStack stack = Items.STONE.getDefaultStack(); final Method method = type.getDeclaredMethod("getFluidState", fluidsType);
NbtCompound fluidTag = stack.getOrCreateSubNbt("fluid"); if (method != null) {
fluidTag.putString("id", Registries.FLUID.getId(fluid.getFluid()).toString()); return fluidVariant -> {
fluidTag.put("attributes", fluid.getNbt()); try {
return FluidState.class.cast(method.invoke(type.cast(fluid), stack)); Object fluids = fluidVariant.getComponents().get(fluidsComponentType).orElse(null);
} catch (Throwable tt) {} if (fluids == null) {
return FALLBACK_METHOD.apply(fluid); return FALLBACK_METHOD.apply(fluidVariant);
}; }
} return (FluidState)method.invoke(type.cast(fluidVariant), fluids);
} catch (Throwable t) {} } catch (Throwable tt) {}
return FALLBACK_METHOD; return FALLBACK_METHOD.apply(fluidVariant);
};
}
}
} catch (Throwable t) {}
return FALLBACK_METHOD;
}).orElse(FALLBACK_METHOD);
}).orElse(FALLBACK_METHOD)); }).orElse(FALLBACK_METHOD));
static FluidState getFullFluidState(FluidVariant variant) { static FluidState getFullFluidState(FluidVariant variant) {