Some more refactoring to move awary from using just one god-tier tick() method

This commit is contained in:
Sollace 2022-12-25 23:21:34 +01:00
parent db52d53d06
commit 67a7c9f16e
6 changed files with 123 additions and 83 deletions

View file

@ -45,10 +45,8 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
private final EntityReference<LivingEntity> owner = new EntityReference<>();
@Nullable
private GoalSelector goals;
@Nullable
private GoalSelector targets;
private Optional<GoalSelector> goals = Optional.empty();
private Optional<GoalSelector> targets = Optional.empty();
private int eatTimer;
@Nullable
@ -59,14 +57,17 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
physics = new EntityPhysics<>(entity, GRAVITY);
entity.getDataTracker().startTracking(MASTER, owner.toNBT());
entity.getDataTracker().startTracking(EATING, 0);
addTicker(physics);
addTicker(this::updateConsumption);
}
@Override
public void setMaster(LivingEntity owner) {
this.owner.set(owner);
entity.getDataTracker().set(MASTER, this.owner.toNBT());
if (targets != null && owner != null) {
initMinionAi();
if (owner != null) {
targets.ifPresent(this::initMinionAi);
}
}
@ -88,16 +89,16 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
}
public Optional<GoalSelector> getTargets() {
return Optional.ofNullable(targets);
return targets;
}
public Optional<GoalSelector> getGoals() {
return Optional.ofNullable(goals);
return goals;
}
public void initAi(GoalSelector goals, GoalSelector targets) {
this.goals = goals;
this.targets = targets;
this.goals = Optional.of(goals);
this.targets = Optional.of(targets);
DynamicTargetGoal targetter = new DynamicTargetGoal((MobEntity)entity);
targets.add(1, targetter);
@ -111,7 +112,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
}
if (owner.isPresent(asWorld())) {
initMinionAi();
initMinionAi(targets);
}
if (entity instanceof CreeperEntity mob) {
@ -122,7 +123,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
}
}
private void initMinionAi() {
private void initMinionAi(GoalSelector targets) {
Predicate<LivingEntity> filter = TargetSelecter.<LivingEntity>notOwnerOrFriend(this, this).and(e -> {
return Equine.of(e)
.filter(eq -> eq instanceof Creature)
@ -147,11 +148,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
return false;
}
@Override
public void tick() {
super.tick();
physics.tick();
private void updateConsumption() {
if (isClient()) {
eatTimer = entity.getDataTracker().get(EATING);
} else if (eatMuffinGoal != null) {
@ -240,8 +237,8 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
}
if (compound.contains("master", NbtElement.COMPOUND_TYPE)) {
owner.fromNBT(compound.getCompound("master"));
if (owner.isPresent(asWorld()) && targets != null) {
initMinionAi();
if (owner.isPresent(asWorld())) {
targets.ifPresent(this::initMinionAi);
}
}
physics.fromNBT(compound);

View file

@ -5,8 +5,7 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.Copyable;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import com.minelittlepony.unicopia.util.*;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemConvertible;
@ -15,7 +14,7 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.Identifier;
import net.minecraft.registry.Registries;
public class ItemTracker implements NbtSerialisable, Copyable<ItemTracker> {
public class ItemTracker implements NbtSerialisable, Copyable<ItemTracker>, Tickable {
public static final long TICKS = 1;
public static final long SECONDS = 20 * TICKS;
public static final long HOURS = 1000 * TICKS;
@ -54,6 +53,17 @@ public class ItemTracker implements NbtSerialisable, Copyable<ItemTracker> {
return ticks -> ticks <= maxTime;
}
private final Living<?> living;
public ItemTracker(Living<?> living) {
this.living = living;
}
@Override
public void tick() {
update(living, living.getArmourStacks());
}
public void update(Living<?> living, Stream<ItemStack> stacks) {
final Set<Trackable> found = new HashSet<>();
final Set<ItemStack> foundStacks = new HashSet<>();

View file

@ -1,14 +1,15 @@
package com.minelittlepony.unicopia.entity;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.jetbrains.annotations.Nullable;
import com.google.common.base.Preconditions;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.SpellContainer;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
@ -17,6 +18,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.advancement.UCriteria;
import com.minelittlepony.unicopia.block.data.DragonBreathStore;
import com.minelittlepony.unicopia.entity.effect.UEffects;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.GlassesItem;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.network.datasync.EffectSync;
@ -24,8 +26,7 @@ import com.minelittlepony.unicopia.network.datasync.Transmittable;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.*;
import net.minecraft.entity.*;
import net.minecraft.entity.damage.DamageSource;
@ -62,9 +63,10 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
private int invinsibilityTicks;
private final Enchantments enchants = new Enchantments(this);
private final List<Tickable> tickers = new ArrayList<>();
private final ItemTracker armour = new ItemTracker();
private final Enchantments enchants = addTicker(new Enchantments(this));
private final ItemTracker armour = addTicker(new ItemTracker(this));
protected Living(T entity, TrackedData<NbtCompound> effect) {
this.entity = entity;
@ -74,6 +76,11 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
entity.getDataTracker().startTracking(CARRIER_ID, Optional.empty());
}
public <Q extends Tickable> Q addTicker(Q tickable) {
tickers.add(Preconditions.checkNotNull(tickable, "tickable"));
return tickable;
}
public boolean isInvisible() {
return invisible && SpellPredicate.IS_DISGUISE.isOn(this);
}
@ -135,7 +142,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
@Override
public void tick() {
armour.update(this, getArmourStacks());
tickers.forEach(Tickable::tick);
try {
getSpellSlot().forEach(spell -> Operation.ofBoolean(spell.tick(this, Situation.BODY)), entity.world.isClient);
@ -157,11 +164,15 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
updateVelocity();
}
enchants.tick();
updateDragonBreath();
prevSneaking = entity.isSneaking();
prevLanded = entity.isOnGround();
}
private void updateDragonBreath() {
if (!entity.world.isClient && (entity instanceof PlayerEntity || entity.hasCustomName())) {
Vec3d targetPos = entity.getRotationVector().multiply(2).add(entity.getEyePos());

View file

@ -80,7 +80,6 @@ public class SunBlindnessStatusEffect extends StatusEffect {
}
return isPositionExposedToSun(entity.world, entity.getBlockPos());
}
public static boolean isPositionExposedToSun(World world, BlockPos pos) {

View file

@ -0,0 +1,41 @@
package com.minelittlepony.unicopia.entity.player;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.HitResult.Type;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
public interface MeteorlogicalUtil {
static boolean isLookingIntoSun(World world, Entity entity) {
// check first whether the world has a sun
if (!world.getDimension().hasSkyLight()) {
return false;
}
// check if sun is obscured by clouds
if (world.hasRain(entity.getBlockPos()) || world.isThundering()) {
return false;
}
// we translate sun angle to a scale of 0-1 (0=sunrise, 1=sunset, >1 nighttime)
final float skyAngle = ((entity.world.getSkyAngle(1) + 0.25F) % 1F) * 2;
float playerYaw = MathHelper.wrapDegrees(entity.getHeadYaw());
float playerAngle = (-entity.getPitch(1) / 90F) / 2F;
// player is facing the other way so flip the yaw to match sun angle
if (playerYaw > 0) {
playerAngle = 1 - playerAngle;
}
playerYaw = Math.abs(playerYaw);
// check if day,
// and player is looking towards the sun, and that there isn't a block obstructing their view
return skyAngle < 1
&& (playerYaw > 89 && playerYaw < 92 || (playerAngle > 0.45F && playerAngle < 0.55F))
&& playerAngle > (skyAngle - 0.04F) && playerAngle < (skyAngle + 0.04F)
&& entity.raycast(100, 1, true).getType() == Type.MISS;
}
}

View file

@ -11,8 +11,7 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.ability.EarthPonyStompAbility;
import com.minelittlepony.unicopia.ability.*;
import com.minelittlepony.unicopia.ability.magic.*;
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
@ -32,7 +31,6 @@ import com.minelittlepony.unicopia.network.MsgPlayerAnimationChange;
import com.minelittlepony.unicopia.util.*;
import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback;
import com.minelittlepony.common.util.animation.LinearInterpolator;
import com.google.common.collect.Lists;
import com.google.common.collect.Streams;
import com.minelittlepony.common.util.animation.Interpolator;
import com.mojang.authlib.GameProfile;
@ -54,12 +52,10 @@ import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.HitResult.Type;
import net.minecraft.util.math.*;
import net.minecraft.world.GameMode;
public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, UpdateCallback {
private static final TrackedData<String> RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.STRING);
static final TrackedData<Float> ENERGY = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
@ -76,9 +72,8 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
private static final TrackedData<NbtCompound> EFFECT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
private final AbilityDispatcher powers = new AbilityDispatcher(this);
private final PlayerPhysics gravity = new PlayerPhysics(this);
private final PlayerPhysics gravity = addTicker(new PlayerPhysics(this));
private final PlayerCharmTracker charms = new PlayerCharmTracker(this);
private final PlayerAttributes attributes = new PlayerAttributes(this);
private final PlayerCamera camera = new PlayerCamera(this);
private final TraitDiscovery discoveries = new TraitDiscovery(this);
@ -88,8 +83,6 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
private final PlayerLevelStore levels;
private final PlayerLevelStore corruption;
private final List<Tickable> tickers;
private final Interpolator interpolator = new LinearInterpolator();
private boolean dirty;
@ -99,9 +92,6 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
private float magicExhaustion = 0;
@Nullable
private Race clientPreferredRace;
private int ticksInSun;
private boolean hasShades;
private int ticksSunImmunity = INITIAL_SUN_IMMUNITY;
@ -112,13 +102,17 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
public Pony(PlayerEntity player) {
super(player, EFFECT);
this.mana = new ManaContainer(this);
this.mana = addTicker(new ManaContainer(this));
this.levels = new PlayerLevelStore(this, LEVEL, true, SoundEvents.ENTITY_PLAYER_LEVELUP);
this.corruption = new PlayerLevelStore(this, CORRUPTION, false, SoundEvents.PARTICLE_SOUL_ESCAPE);
this.tickers = Lists.newArrayList(gravity, mana, attributes);
player.getDataTracker().startTracking(RACE, Race.DEFAULT_ID);
player.getDataTracker().startTracking(HANGING_POSITION, Optional.empty());
addTicker(this::updateAnimations);
addTicker(this::updateBatPonyAbilities);
addTicker(this::updateCorruptionDecay);
addTicker(new PlayerAttributes(this));
}
public static void registerAttributes(DefaultAttributeContainer.Builder builder) {
@ -299,21 +293,24 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
if (isClient()) {
if (entity.hasVehicle() && entity.isSneaking()) {
Entity ridee = entity.getVehicle();
Entity vehicle = entity.getVehicle();
if (ridee instanceof Trap) {
if (((Trap)ridee).attemptDismount(entity)) {
if (vehicle instanceof Trap) {
if (((Trap)vehicle).attemptDismount(entity)) {
entity.stopRiding();
entity.refreshPositionAfterTeleport(vehicle.getPos());
Living.transmitPassengers(vehicle);
} else {
entity.setSneaking(false);
}
} else {
entity.stopRiding();
Living.transmitPassengers(ridee);
entity.refreshPositionAfterTeleport(vehicle.getPos());
Living.transmitPassengers(vehicle);
}
}
}
magicExhaustion = ManaConsumptionUtil.burnFood(entity, magicExhaustion);
powers.tick();
@ -355,15 +352,16 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
return state.isSolidSurface(asWorld(), pos, entity, Direction.DOWN);
}
@Override
public void tick() {
if (ticksSunImmunity > 0) {
ticksSunImmunity--;
}
private void updateAnimations() {
if (animationDuration >= 0 && --animationDuration <= 0) {
setAnimation(Animation.NONE);
}
}
private void updateBatPonyAbilities() {
if (ticksSunImmunity > 0) {
ticksSunImmunity--;
}
if (isHanging()) {
((LivingEntityDuck)entity).setLeaningPitch(0);
@ -381,30 +379,12 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
this.hasShades = hasShades;
if (!hasShades && ticksSunImmunity <= 0) {
float skyAngle = ((entity.world.getSkyAngle(1) + 0.25F) % 1F) * 2;
float playerAngle = (-entity.getPitch(1) / 90F) / 2F;
float playerYaw = MathHelper.wrapDegrees(entity.getHeadYaw());
if (playerYaw > 0) {
playerAngle = 1 - playerAngle;
}
playerYaw = Math.abs(playerYaw);
if (skyAngle < 1
&& (playerYaw > 89 && playerYaw < 92 || (playerAngle > 0.45F && playerAngle < 0.55F))
&& playerAngle > (skyAngle - 0.04F) && playerAngle < (skyAngle + 0.04F)) {
if (entity.raycast(100, 1, true).getType() == Type.MISS) {
if (!isClient()) {
entity.addStatusEffect(new StatusEffectInstance(UEffects.SUN_BLINDNESS, SunBlindnessStatusEffect.MAX_DURATION, 2, true, false));
UCriteria.LOOK_INTO_SUN.trigger(entity);
} else if (isClientPlayer()) {
InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_EARS_RINGING, entity.getId());
}
}
if (!hasShades && ticksSunImmunity <= 0 && MeteorlogicalUtil.isLookingIntoSun(asWorld(), entity)) {
if (!isClient()) {
entity.addStatusEffect(new StatusEffectInstance(UEffects.SUN_BLINDNESS, SunBlindnessStatusEffect.MAX_DURATION, 2, true, false));
UCriteria.LOOK_INTO_SUN.trigger(entity);
} else if (isClientPlayer()) {
InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_EARS_RINGING, entity.getId());
}
}
@ -424,7 +404,9 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
ticksInSun--;
}
}
}
private void updateCorruptionDecay() {
if (!isClient() && !UItems.ALICORN_AMULET.isApplicable(entity)) {
if (entity.age % (10 * ItemTracker.SECONDS) == 0) {
if (entity.world.random.nextInt(100) == 0) {
@ -443,11 +425,11 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
setDirty();
}
}
}
tickers.forEach(Tickable::tick);
@Override
public void tick() {
super.tick();
sendCapabilities();
}