Further refactorings

This commit is contained in:
Sollace 2022-12-19 20:45:02 +01:00
parent a3163d431f
commit eed112ef4a
30 changed files with 158 additions and 154 deletions

View file

@ -21,24 +21,6 @@ public interface Owned<E extends Entity> {
@Nullable
E getMaster();
/**
* Updates the owner of this object.
*/
void setMaster(@Nullable E owner);
/**
* Updated the owner of this object to be the same as another.
*
* @param sibling
*/
default void setMaster(Owned<? extends E> sibling) {
setMaster(sibling.getMaster());
}
default boolean hasMaster() {
return getMaster() != null;
}
/**
* Gets the unique entity id of the entity that holds this object.
* <p>
@ -58,4 +40,20 @@ public interface Owned<E extends Entity> {
default boolean hasCommonOwner(Owned<?> sibling) {
return getMasterId().isPresent() && getMasterId().equals(sibling.getMasterId());
}
interface Mutable<E extends Entity> {
/**
* Updates the owner of this object.
*/
void setMaster(@Nullable E owner);
/**
* Updated the owner of this object to be the same as another.
*
* @param sibling
*/
default void setMaster(Owned<? extends E> sibling) {
setMaster(sibling.getMaster());
}
}
}

View file

@ -16,7 +16,21 @@ import net.minecraft.entity.Entity;
* @param <E> The type of object that owns us.
*/
public interface WeaklyOwned<E extends Entity> extends Owned<E>, WorldConvertable {
EntityReference<E> getMasterReference();
@Nullable
@Override
default E getMaster() {
return getMasterReference().get(asWorld());
}
@Override
default Optional<UUID> getMasterId() {
return getMasterReference().getId();
}
interface Mutable<E extends Entity> extends WeaklyOwned<E>, Owned.Mutable<E> {
@Override
EntityReference<E> getMasterReference();
/**
@ -38,15 +52,5 @@ public interface WeaklyOwned<E extends Entity> extends Owned<E>, WorldConvertabl
default void setMaster(E master) {
getMasterReference().set(master);
}
@Nullable
@Override
default E getMaster() {
return getMasterReference().get(asWorld());
}
@Override
default Optional<UUID> getMasterId() {
return getMasterReference().getId();
}
}

View file

@ -16,7 +16,6 @@ import net.minecraft.block.FenceBlock;
import net.minecraft.block.LeavesBlock;
import net.minecraft.block.WallBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.sound.SoundCategory;
@ -127,9 +126,9 @@ public class UnicornTeleportAbility implements Ability<Pos> {
return;
}
LivingEntity player = teleportee.getMaster();
Entity participant = teleportee.asEntity();
if (player == null) {
if (participant == null) {
return;
}
@ -137,24 +136,24 @@ public class UnicornTeleportAbility implements Ability<Pos> {
double distance = destination.distanceTo(teleportee) / 10;
if (player.hasVehicle()) {
Entity mount = player.getVehicle();
if (participant.hasVehicle()) {
Entity mount = participant.getVehicle();
player.stopRiding();
participant.stopRiding();
Living.transmitPassengers(mount);
}
Vec3d offset = teleportee.getOriginVector().subtract(teleporter.getOriginVector());
player.teleport(
destination.x + offset.x + (player.getX() - Math.floor(player.getX())),
participant.teleport(
destination.x + offset.x + (participant.getX() - Math.floor(participant.getX())),
destination.y + offset.y,
destination.z + offset.z + (player.getZ() - Math.floor(player.getZ())));
destination.z + offset.z + (participant.getZ() - Math.floor(participant.getZ())));
teleporter.subtractEnergyCost(distance);
player.fallDistance /= distance;
participant.fallDistance /= distance;
player.world.playSound(null, destination.pos(), USounds.ENTITY_PLAYER_UNICORN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
participant.world.playSound(null, destination.pos(), USounds.ENTITY_PLAYER_UNICORN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
}
private boolean enterable(World w, BlockPos pos) {

View file

@ -25,7 +25,8 @@ import net.minecraft.world.GameRules;
/**
* Interface for any magically capable entities that can cast or persist spells.
*/
public interface Caster<E extends Entity> extends Owned<LivingEntity>,
public interface Caster<E extends Entity> extends
Owned<LivingEntity>,
Levelled,
Affine,
ParticleSource<E>,
@ -43,6 +44,21 @@ public interface Caster<E extends Entity> extends Owned<LivingEntity>,
*/
boolean subtractEnergyCost(double amount);
/**
* Gets the entity who originally cast the currently active spell.
* @return
*/
@Override
LivingEntity getMaster();
/**
* Gets the original caster responsible for this spell.
* If none is found, will return itself.
*/
default Caster<?> getOriginatingCaster() {
return of(getMaster()).orElse(this);
}
default boolean canModifyAt(BlockPos pos) {
return canModifyAt(pos, ModificationType.EITHER);
}

View file

@ -11,7 +11,6 @@ import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.UParticles;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.nbt.NbtCompound;
/**
@ -55,9 +54,8 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I
}
}
LivingEntity owner = source.getMaster();
Entity entity = getDisguise().getAppearance();
Entity owner = source.asEntity();
Entity appearance = getDisguise().getAppearance();
if (isSuppressed()) {
suppressionCounter--;
@ -67,9 +65,9 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I
((Pony)source).setInvisible(false);
}
if (entity != null) {
entity.setInvisible(true);
entity.setPos(entity.getX(), Integer.MIN_VALUE, entity.getY());
if (appearance != null) {
appearance.setInvisible(true);
appearance.setPos(appearance.getX(), Integer.MIN_VALUE, appearance.getY());
}
return true;

View file

@ -12,7 +12,6 @@ import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.BlockState;
import net.minecraft.entity.LivingEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.Vec3d;
@ -55,19 +54,13 @@ public class RainboomAbilitySpell extends AbstractSpell {
// source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
}
LivingEntity owner = source.getMaster();
if (owner == null) {
return false;
}
source.findAllEntitiesInRange(RADIUS).forEach(e -> {
e.damage(MagicalDamageSource.create("rainboom", source).setBreakSunglasses(), 6);
});
EFFECT_RANGE.translate(source.getOrigin()).getBlockPositions().forEach(pos -> {
BlockState state = source.asWorld().getBlockState(pos);
if (state.isIn(UTags.FRAGILE) && source.canModifyAt(pos, ModificationType.PHYSICAL)) {
owner.world.breakBlock(pos, true);
source.asWorld().breakBlock(pos, true);
}
});

View file

@ -12,7 +12,7 @@ import com.minelittlepony.unicopia.item.GemstoneItem;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.world.World;
@ -51,11 +51,7 @@ public final class ThrowableSpell extends AbstractDelegatingSpell {
public Optional<MagicProjectileEntity> throwProjectile(Caster<?> caster, float divergance) {
World world = caster.asWorld();
LivingEntity entity = caster.getMaster();
if (entity == null) {
return Optional.empty();
}
Entity entity = caster.asEntity();
caster.playSound(USounds.SPELL_CAST_SHOOT, 0.7F, 0.4F / (world.random.nextFloat() * 0.4F + 0.8F));

View file

@ -30,26 +30,28 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pla
@Override
public boolean tick(Caster<?> source, Situation situation) {
source.getMaster().setGlowing(true);
Caster<?> originator = source.getOriginatingCaster();
originator.asEntity().setGlowing(true);
ticks--;
if (source.isClient()) {
if (originator.isClient()) {
return !isDead() || ticks >= -10;
}
if (ticks == 0) {
target.ifPresent(source.asWorld(), target -> {
target.ifPresent(originator.asWorld(), target -> {
Vec3d destinationPos = target.getPos();
Vec3d destinationVel = target.getVelocity();
Vec3d sourcePos = source.getMaster().getPos();
Vec3d sourceVel = source.getMaster().getVelocity();
Vec3d sourcePos = originator.getOriginVector();
Vec3d sourceVel = originator.asEntity().getVelocity();
teleport(target, sourcePos, sourceVel);
teleport(source.getMaster(), destinationPos, destinationVel);
source.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F);
teleport(originator.asEntity(), destinationPos, destinationVel);
originator.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F);
});
}
@ -94,7 +96,7 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pla
@Override
public void onDestroyed(Caster<?> caster) {
caster.getMaster().setGlowing(false);
caster.getOriginatingCaster().asEntity().setGlowing(false);
target.ifPresent(caster.asWorld(), e -> e.setGlowing(false));
}

View file

@ -13,7 +13,6 @@ import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.Block;
@ -73,7 +72,7 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileDele
return new Sphere(false, Math.max(0, 4 + getTraits().get(Trait.POWER))).translate(source.getOrigin()).getBlockPositions().reduce(false,
(r, i) -> source.canModifyAt(i) && applyBlocks(source.asWorld(), i),
(a, b) -> a || b)
|| applyEntities(null, source.asWorld(), source.getOriginVector());
|| applyEntities(source, source.getOriginVector());
}
protected void generateParticles(Caster<?> source) {
@ -124,17 +123,19 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileDele
return false;
}
protected boolean applyEntities(@Nullable Entity owner, World world, Vec3d pos) {
return !VecHelper.findInRange(owner, world, pos, Math.max(0, 3 + getTraits().get(Trait.POWER)), i -> applyEntitySingle(owner, world, i)).isEmpty();
protected boolean applyEntities(Caster<?> source, Vec3d pos) {
return source.findAllEntitiesInRange(Math.max(0, 3 + getTraits().get(Trait.POWER)), i -> applyEntitySingle(source, i)).count() > 0;
}
protected boolean applyEntitySingle(@Nullable Entity owner, World world, Entity e) {
if ((!e.equals(owner) ||
(owner instanceof PlayerEntity && !EquinePredicates.PLAYER_UNICORN.test(owner))) && !(e instanceof ItemEntity)
protected boolean applyEntitySingle(Caster<?> source, Entity e) {
LivingEntity master = source.getMaster();
if ((!(e.equals(source.asEntity()) || e.equals(master)) ||
(master instanceof PlayerEntity && !EquinePredicates.PLAYER_UNICORN.test(master))) && !(e instanceof ItemEntity)
&& !(e instanceof Caster<?>)) {
e.setOnFireFor(60);
e.damage(getDamageCause(e, (LivingEntity)owner), 0.1f);
playEffect(world, e.getBlockPos());
e.damage(getDamageCause(e, master), 0.1f);
playEffect(source.asWorld(), e.getBlockPos());
return true;
}

View file

@ -15,7 +15,6 @@ import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.*;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.TntEntity;
import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.particle.ParticleTypes;
@ -67,21 +66,21 @@ public class IceSpell extends AbstractSpell {
source.subtractEnergyCost(Math.min(10, blocksAffected));
return applyEntities(source.getMaster(), source.asWorld(), source.getOriginVector()) && situation == Situation.PROJECTILE;
return applyEntities(source, source.getOriginVector()) && situation == Situation.PROJECTILE;
}
protected boolean applyEntities(LivingEntity owner, World world, Vec3d pos) {
return !VecHelper.findInRange(owner, world, pos, 3, i -> applyEntitySingle(owner, i)).isEmpty();
protected boolean applyEntities(Caster<?> source, Vec3d pos) {
return !VecHelper.findInRange(source.asEntity(), source.asWorld(), pos, 3, i -> applyEntitySingle(source, i)).isEmpty();
}
protected boolean applyEntitySingle(LivingEntity owner, Entity e) {
protected boolean applyEntitySingle(Caster<?> source, Entity e) {
if (e instanceof TntEntity) {
e.remove(RemovalReason.DISCARDED);
e.getEntityWorld().setBlockState(e.getBlockPos(), Blocks.TNT.getDefaultState());
} else if (e.isOnFire()) {
e.extinguish();
} else {
e.damage(MagicalDamageSource.create("cold", owner), 2);
e.damage(MagicalDamageSource.create("cold", source.getMaster()), 2);
}
return true;

View file

@ -54,7 +54,7 @@ public class InfernoSpell extends FireSpell {
Vec3d vec = shape.computePoint(w.random).add(origin);
if (!applyBlocks(w, new BlockPos(vec))) {
applyEntities(source.getMaster(), w, vec);
applyEntities(source, vec);
}
}
}

View file

@ -34,10 +34,12 @@ public class MindSwapSpell extends MimicSpell {
super.onDestroyed(caster);
if (initialized && !caster.isClient()) {
counterpart.ifPresent(caster.asWorld(), e -> {
EntitySwap.ALL.accept(e, caster.getMaster());
LivingEntity master = caster.getMaster();
EntitySwap.ALL.accept(e, master);
Inventory.swapInventories(
e, myStoredInventory.or(() -> Inventory.of(e)),
caster.getMaster(), theirStoredInventory.or(() -> Inventory.of(caster.getMaster())),
master, theirStoredInventory.or(() -> Inventory.of(master)),
a -> {},
a -> {}
);
@ -60,13 +62,15 @@ public class MindSwapSpell extends MimicSpell {
initialized = true;
setDirty();
counterpart.ifPresent(caster.asWorld(), e -> {
LivingEntity master = caster.getMaster();
setDisguise(e);
Caster<?> other = Caster.of(e).get();
SpellType.MIMIC.withTraits().apply(other).setDisguise(caster.getMaster());
SpellType.MIMIC.withTraits().apply(other).setDisguise(master);
EntitySwap.ALL.accept(caster.getMaster(), e);
EntitySwap.ALL.accept(master, e);
Inventory.swapInventories(
caster.getMaster(), Inventory.of(caster.getMaster()),
master, Inventory.of(master),
e, Inventory.of(e),
a -> myStoredInventory = Optional.of(a),
a -> theirStoredInventory = Optional.of(a)
@ -78,7 +82,7 @@ public class MindSwapSpell extends MimicSpell {
}
if (counterpart.getId().isPresent() && counterpart.get(caster.asWorld()) == null) {
caster.getMaster().damage(DamageSource.MAGIC, Float.MAX_VALUE);
caster.getOriginatingCaster().asEntity().damage(DamageSource.MAGIC, Float.MAX_VALUE);
setDead();
return false;
}

View file

@ -14,9 +14,7 @@ import com.minelittlepony.unicopia.util.Weighted;
import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.*;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
@ -142,7 +140,7 @@ public class NecromancySpell extends AbstractAreaEffectSpell {
minion.equipStack(EquipmentSlot.HEAD, Items.IRON_HELMET.getDefaultStack());
Equine.of(minion).filter(eq -> eq instanceof Creature).ifPresent(eq -> {
((Creature)eq).setMaster(source);
((Creature)eq).setMaster(source.getMaster());
});
source.asWorld().spawnEntity(minion);

View file

@ -4,6 +4,8 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.magic.Caster;
@ -107,6 +109,7 @@ public class SiphoningSpell extends AbstractAreaEffectSpell {
}
private void collectHealth(Caster<?> source) {
@Nullable
LivingEntity owner = source.getMaster();
float maxHealthGain = owner == null ? 0 : owner.getMaxHealth() - owner.getHealth();

View file

@ -171,7 +171,7 @@ public class WorldRenderDelegate {
matrices.pop();
if (pony instanceof Living && pony.getPhysics().isGravityNegative()) {
flipAngles(((Living<?>)pony).getMaster());
flipAngles(pony.asEntity());
}
}
}

View file

@ -23,7 +23,7 @@ import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.text.Text;
import net.minecraft.world.World;
public class CastSpellEntity extends LightEmittingEntity implements Caster<CastSpellEntity>, WeaklyOwned<LivingEntity> {
public class CastSpellEntity extends LightEmittingEntity implements Caster<CastSpellEntity>, WeaklyOwned.Mutable<LivingEntity> {
private static final TrackedData<Float> GRAVITY = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<NbtCompound> EFFECT = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
@ -88,6 +88,11 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
setMaster(caster);
}
@Override
public LivingEntity getMaster() {
return WeaklyOwned.Mutable.super.getMaster();
}
@Override
public LevelStore getLevel() {
return level;

View file

@ -33,7 +33,7 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.util.math.MathHelper;
public class Creature extends Living<LivingEntity> implements WeaklyOwned<LivingEntity> {
public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutable<LivingEntity> {
private static final TrackedData<NbtCompound> EFFECT = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
private static final TrackedData<NbtCompound> MASTER = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
public static final TrackedData<Float> GRAVITY = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.FLOAT);

View file

@ -53,7 +53,7 @@ public class Enchantments implements NbtSerialisable, Tickable {
@Override
public void tick() {
UEnchantments.REGISTRY.forEach(ench -> {
int level = EnchantmentHelper.getEquipmentLevel(ench, entity.getMaster());
int level = EnchantmentHelper.getEquipmentLevel(ench, entity.asEntity());
boolean active = level > 0;

View file

@ -41,7 +41,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent;
public class FairyEntity extends PathAwareEntity implements DynamicLightSource, WeaklyOwned<LivingEntity> {
public class FairyEntity extends PathAwareEntity implements DynamicLightSource, WeaklyOwned.Mutable<LivingEntity> {
private final EntityReference<LivingEntity> owner = new EntityReference<>();
private final EntityReference<LivingEntity> assignment = new EntityReference<>();

View file

@ -108,11 +108,11 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider
if (source instanceof Pony) {
Pony player = (Pony)source;
source.getMaster().setInvisible(true);
source.asEntity().setInvisible(true);
player.setInvisible(true);
if (entity instanceof Owned) {
((Owned<LivingEntity>)entity).setMaster(player);
if (entity instanceof Owned.Mutable) {
((Owned.Mutable<LivingEntity>)entity).setMaster(player);
}
if (entity instanceof PlayerEntity) {
@ -120,7 +120,7 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider
}
}
return !isDead() && !source.getMaster().isDead();
return !isDead() && !source.asEntity().isDead();
}
public static abstract class PlayerAccess extends PlayerEntity {

View file

@ -16,7 +16,7 @@ public class EndermanBehaviour extends EntityBehaviour<EndermanEntity> {
entity.setTarget(null);
}
ItemStack stack = source.getMaster().getStackInHand(Hand.MAIN_HAND);
ItemStack stack = source.asEntity().getStackInHand(Hand.MAIN_HAND);
if (stack.getItem() instanceof BlockItem bi) {
entity.setCarriedBlock(bi.getBlock().getDefaultState());
} else {

View file

@ -134,7 +134,7 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi
remove();
entity = InteractionManager.instance().createPlayer(source.asEntity(), profile);
entity.setCustomName(source.getMaster().getName());
entity.setCustomName(source.asEntity().getName());
((PlayerEntity)entity).readNbt(nbt.getCompound("playerNbt"));
if (nbt.contains("playerVisibleParts", NbtElement.BYTE_TYPE)) {
entity.getDataTracker().set(Disguise.PlayerAccess.getModelBitFlag(), nbt.getByte("playerVisibleParts"));

View file

@ -42,7 +42,7 @@ public class CorruptInfluenceStatusEffect extends StatusEffect {
}
if (nearby > 1) {
if (Equine.of(entity).filter(eq -> eq instanceof Owned<?> o && o.hasMaster()).isPresent()) {
if (Equine.of(entity).filter(eq -> eq instanceof Owned<?> o && o.getMaster() != null).isPresent()) {
return;
}
@ -59,8 +59,8 @@ public class CorruptInfluenceStatusEffect extends StatusEffect {
clone.copyPositionAndRotation(entity);
Equine.of(clone).ifPresent(eq -> {
if (eq instanceof Owned) {
((Owned<Entity>)eq).setMaster(mob);
if (eq instanceof Owned.Mutable) {
((Owned.Mutable<Entity>)eq).setMaster(mob);
}
});
mob.world.spawnEntity(clone);

View file

@ -288,23 +288,11 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
return interpolator;
}
/**
* @deprecated use asEntity()
*/
@Override
@Deprecated(forRemoval = true)
public final LivingEntity getMaster() {
return asEntity();
}
/**
* @deprecated Pony cannot belong to other entities
*/
@Override
@Deprecated
public void setMaster(@Nullable LivingEntity owner) {
}
public void onSpawn() {
if (entity.world instanceof ServerWorld sw
&& getObservedSpecies() == Race.BAT

View file

@ -16,7 +16,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.GameMode;
public class DummyClientPlayerEntity extends AbstractClientPlayerEntity implements Owned<PlayerEntity> {
public class DummyClientPlayerEntity extends AbstractClientPlayerEntity implements Owned<PlayerEntity>, Owned.Mutable<PlayerEntity> {
private PlayerListEntry playerInfo;

View file

@ -12,7 +12,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class DummyPlayerEntity extends PlayerEntity implements Owned<PlayerEntity> {
public class DummyPlayerEntity extends PlayerEntity implements Owned<PlayerEntity>, Owned.Mutable<PlayerEntity> {
private PlayerEntity owner;

View file

@ -116,7 +116,9 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
@Override
public void onUnequipped(Living<?> wearer, long timeWorn) {
if (wearer.getMaster() instanceof PlayerEntity player && player.isCreative()) {
LivingEntity entity = wearer.asEntity();
if (entity instanceof PlayerEntity player && player.isCreative()) {
return;
}
@ -125,24 +127,24 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
LocalDifficulty difficulty = wearer.asWorld().getLocalDifficulty(wearer.getOrigin());
float amount = attachedTime * (1 + difficulty.getClampedLocalDifficulty());
amount = Math.min(amount, wearer.getMaster().getMaxHealth());
amount = Math.min(amount, entity.getMaxHealth());
if (wearer.getMaster() instanceof PlayerEntity) {
((PlayerEntity)wearer.getMaster()).getHungerManager().setFoodLevel(1);
if (entity instanceof PlayerEntity player) {
player.getHungerManager().setFoodLevel(1);
}
wearer.getMaster().damage(MagicalDamageSource.ALICORN_AMULET, amount);
wearer.getMaster().addStatusEffect(new StatusEffectInstance(StatusEffects.NAUSEA, 200, 1));
entity.damage(MagicalDamageSource.ALICORN_AMULET, amount);
entity.addStatusEffect(new StatusEffectInstance(StatusEffects.NAUSEA, 200, 1));
if (timeWorn > ItemTracker.HOURS) {
wearer.getMaster().addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS, 200, 3));
entity.addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS, 200, 3));
}
if (attachedTime > 120) {
wearer.getMaster().takeKnockback(1, 1, 1);
entity.takeKnockback(1, 1, 1);
wearer.updateVelocity();
}
EFFECT_SCALES.keySet().forEach(attribute -> {
EntityAttributeInstance instance = wearer.getMaster().getAttributeInstance(attribute);
EntityAttributeInstance instance = entity.getAttributeInstance(attribute);
@Nullable
EntityAttributeModifier modifier = instance.getModifier(EFFECT_UUID);
if (modifier != null) {
@ -207,8 +209,8 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
reserves.getExertion().add(reserves.getExertion().getMax());
reserves.getEnergy().add(reserves.getEnergy().getMax() / 2F);
living.getMaster().removeStatusEffect(StatusEffects.WEAKNESS);
living.getMaster().removeStatusEffect(StatusEffects.NAUSEA);
living.asEntity().removeStatusEffect(StatusEffects.WEAKNESS);
living.asEntity().removeStatusEffect(StatusEffects.NAUSEA);
}
if (!poweringUp) {
@ -226,7 +228,7 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab
if (fullSecond) {
EFFECT_SCALES.entrySet().forEach(attribute -> {
float seconds = (float)attachedTicks / ItemTracker.SECONDS;
EntityAttributeInstance instance = living.getMaster().getAttributeInstance(attribute.getKey());
EntityAttributeInstance instance = living.asEntity().getAttributeInstance(attribute.getKey());
@Nullable
EntityAttributeModifier modifier = instance.getModifier(EFFECT_UUID);
float desiredValue = attribute.getValue() * seconds;

View file

@ -9,7 +9,6 @@ import com.minelittlepony.unicopia.entity.Living;
import net.minecraft.enchantment.EnchantmentTarget;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.entity.attribute.EntityAttributeModifier;
@ -34,9 +33,8 @@ public class AttributedEnchantment extends SimpleEnchantment {
@Override
public void onUserTick(Living<?> user, int level) {
if (shouldChangeModifiers(user, level)) {
LivingEntity entity = user.getMaster();
modifiers.forEach((attr, modifierSupplier) -> {
EntityAttributeInstance instance = entity.getAttributeInstance(attr);
EntityAttributeInstance instance = user.asEntity().getAttributeInstance(attr);
EntityAttributeModifier modifier = modifierSupplier.get(user, level);
@ -48,9 +46,8 @@ public class AttributedEnchantment extends SimpleEnchantment {
@Override
public void onUnequipped(Living<?> user) {
LivingEntity entity = user.getMaster();
modifiers.forEach((attr, modifierSupplier) -> {
EntityAttributeInstance instance = entity.getAttributeInstance(attr);
EntityAttributeInstance instance = user.asEntity().getAttributeInstance(attr);
instance.tryRemoveModifier(modifierSupplier.get(user, 1).getId());
});

View file

@ -46,8 +46,8 @@ public class ClientNetworkHandlerImpl implements ClientNetworkHandler {
entity.setId(packet.getId());
entity.setUuid(packet.getUuid());
if (entity instanceof Owned) {
((Owned<Entity>) entity).setMaster(world.getEntityById(packet.getEntityData()));
if (entity instanceof Owned.Mutable) {
((Owned.Mutable<Entity>) entity).setMaster(world.getEntityById(packet.getEntityData()));
}
if (entity.getType() == UEntities.MAGIC_BEAM) {

View file

@ -7,6 +7,7 @@ import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.Owned;
import com.minelittlepony.unicopia.ability.magic.Affine;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Levelled;
@ -52,7 +53,7 @@ import net.minecraft.world.World;
*
* Can also carry a spell if needed.
*/
public class MagicProjectileEntity extends ThrownItemEntity implements Caster<MagicProjectileEntity> {
public class MagicProjectileEntity extends ThrownItemEntity implements Caster<MagicProjectileEntity>, Owned.Mutable<LivingEntity> {
private static final TrackedData<Float> DAMAGE = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<Float> GRAVITY = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<Boolean> HYDROPHOBIC = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.BOOLEAN);