mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-20 03:44:23 +01:00
Merge branch '1.20.1' of https://github.com/LingVarr/Unicopia into 1.20.1
This commit is contained in:
commit
e1cc467b05
43 changed files with 618 additions and 226 deletions
|
@ -33,7 +33,7 @@ public interface EquinePredicates {
|
||||||
Predicate<Entity> IS_CASTER = e -> !e.isRemoved() && (e instanceof Caster || IS_PLAYER.test(e));
|
Predicate<Entity> IS_CASTER = e -> !e.isRemoved() && (e instanceof Caster || IS_PLAYER.test(e));
|
||||||
Predicate<Entity> IS_PLACED_SPELL = e -> e instanceof Caster && !e.isRemoved();
|
Predicate<Entity> IS_PLACED_SPELL = e -> e instanceof Caster && !e.isRemoved();
|
||||||
|
|
||||||
Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity)) && !(e instanceof ItemEntity);
|
Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity)) && !(e instanceof ItemEntity) && !(e instanceof ExperienceOrbEntity);
|
||||||
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
|
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
|
||||||
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);
|
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,6 @@ 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.network.Channel;
|
import com.minelittlepony.unicopia.network.Channel;
|
||||||
import com.minelittlepony.unicopia.network.MsgCasterLookRequest;
|
import com.minelittlepony.unicopia.network.MsgCasterLookRequest;
|
||||||
import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect;
|
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
|
||||||
import com.minelittlepony.unicopia.server.world.Ether;
|
import com.minelittlepony.unicopia.server.world.Ether;
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
|
|
||||||
|
@ -24,6 +20,7 @@ import net.minecraft.nbt.*;
|
||||||
import net.minecraft.registry.*;
|
import net.minecraft.registry.*;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
@ -40,11 +37,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
@Nullable
|
@Nullable
|
||||||
private RegistryKey<World> dimension;
|
private RegistryKey<World> dimension;
|
||||||
|
|
||||||
/**
|
|
||||||
* The visual effect
|
|
||||||
*/
|
|
||||||
private final ParticleHandle particlEffect = new ParticleHandle();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of the placed counterpart of this spell.
|
* ID of the placed counterpart of this spell.
|
||||||
*/
|
*/
|
||||||
|
@ -64,6 +56,9 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
public float pitch;
|
public float pitch;
|
||||||
public float yaw;
|
public float yaw;
|
||||||
|
|
||||||
|
private int prevAge;
|
||||||
|
private int age;
|
||||||
|
|
||||||
private Optional<Vec3d> position = Optional.empty();
|
private Optional<Vec3d> position = Optional.empty();
|
||||||
|
|
||||||
public PlaceableSpell(CustomisedSpellType<?> type) {
|
public PlaceableSpell(CustomisedSpellType<?> type) {
|
||||||
|
@ -75,15 +70,13 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public float getAge(float tickDelta) {
|
||||||
public Collection<Spell> getDelegates() {
|
return MathHelper.lerp(tickDelta, prevAge, age);
|
||||||
return List.of(spell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDead() {
|
public Collection<Spell> getDelegates() {
|
||||||
super.setDead();
|
return List.of(spell);
|
||||||
particlEffect.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,14 +108,11 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spell instanceof PlacementDelegate delegate) {
|
prevAge = age;
|
||||||
delegate.updatePlacement(source, this);
|
if (age < 25) {
|
||||||
|
age++;
|
||||||
}
|
}
|
||||||
|
|
||||||
getParticleEffectAttachment(source).ifPresent(p -> {
|
|
||||||
p.setAttribute(Attachment.ATTR_COLOR, spell.getType().getColor());
|
|
||||||
});
|
|
||||||
|
|
||||||
return super.tick(source, Situation.GROUND);
|
return super.tick(source, Situation.GROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,12 +190,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
return castEntity.getTarget().map(EntityValues::pos);
|
return castEntity.getTarget().map(EntityValues::pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Attachment> getParticleEffectAttachment(Caster<?> source) {
|
|
||||||
return particlEffect.update(getUuid(), source, spawner -> {
|
|
||||||
spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.MAGIC_RUNES, pitch + 90, yaw), Vec3d.ZERO, Vec3d.ZERO);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Optional<World> getWorld(Caster<?> source) {
|
protected Optional<World> getWorld(Caster<?> source) {
|
||||||
return Optional.ofNullable(dimension)
|
return Optional.ofNullable(dimension)
|
||||||
.map(dim -> source.asWorld().getServer().getWorld(dim));
|
.map(dim -> source.asWorld().getServer().getWorld(dim));
|
||||||
|
@ -214,11 +198,15 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
@Override
|
@Override
|
||||||
public void toNBT(NbtCompound compound) {
|
public void toNBT(NbtCompound compound) {
|
||||||
super.toNBT(compound);
|
super.toNBT(compound);
|
||||||
|
compound.putInt("age", age);
|
||||||
compound.putFloat("pitch", pitch);
|
compound.putFloat("pitch", pitch);
|
||||||
compound.putFloat("yaw", yaw);
|
compound.putFloat("yaw", yaw);
|
||||||
position.ifPresent(pos -> {
|
position.ifPresent(pos -> {
|
||||||
compound.put("position", NbtSerialisable.writeVector(pos));
|
compound.put("position", NbtSerialisable.writeVector(pos));
|
||||||
});
|
});
|
||||||
|
if (placedSpellId != null) {
|
||||||
|
compound.putUuid("placedSpellId", placedSpellId);
|
||||||
|
}
|
||||||
if (dimension != null) {
|
if (dimension != null) {
|
||||||
compound.putString("dimension", dimension.getValue().toString());
|
compound.putString("dimension", dimension.getValue().toString());
|
||||||
}
|
}
|
||||||
|
@ -229,9 +217,11 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
super.fromNBT(compound);
|
super.fromNBT(compound);
|
||||||
|
age = compound.getInt("age");
|
||||||
pitch = compound.getFloat("pitch");
|
pitch = compound.getFloat("pitch");
|
||||||
yaw = compound.getFloat("yaw");
|
yaw = compound.getFloat("yaw");
|
||||||
position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.FLOAT_TYPE))) : Optional.empty();
|
position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.FLOAT_TYPE))) : Optional.empty();
|
||||||
|
placedSpellId = compound.containsUuid("placedSpellId") ? compound.getUuid("placedSpellId") : null;
|
||||||
if (compound.contains("dimension", NbtElement.STRING_TYPE)) {
|
if (compound.contains("dimension", NbtElement.STRING_TYPE)) {
|
||||||
Identifier id = Identifier.tryParse(compound.getString("dimension"));
|
Identifier id = Identifier.tryParse(compound.getString("dimension"));
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
|
@ -260,9 +250,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface PlacementDelegate {
|
public interface PlacementDelegate {
|
||||||
|
|
||||||
void onPlaced(Caster<?> source, PlaceableSpell parent, CastSpellEntity entity);
|
void onPlaced(Caster<?> source, PlaceableSpell parent, CastSpellEntity entity);
|
||||||
|
|
||||||
void updatePlacement(Caster<?> source, PlaceableSpell parent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class RainboomAbilitySpell extends AbstractSpell {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (source.isClient()) {
|
if (source.isClient()) {
|
||||||
// source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
|
//source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
source.findAllEntitiesInRange(RADIUS).forEach(e -> {
|
source.findAllEntitiesInRange(RADIUS).forEach(e -> {
|
||||||
|
|
|
@ -29,7 +29,7 @@ public interface TimedSpell extends Spell {
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getPercentTimeRemaining(float tickDelta) {
|
public float getPercentTimeRemaining(float tickDelta) {
|
||||||
return MathHelper.lerp(tickDelta, prevDuration, duration) / maxDuration;
|
return MathHelper.lerp(tickDelta, prevDuration, duration) / (float)maxDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTicksRemaining() {
|
public int getTicksRemaining() {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.minelittlepony.unicopia.entity.EntityReference;
|
||||||
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.particle.FollowingParticleEffect;
|
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||||
|
@ -16,6 +15,7 @@ import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.ItemEntity;
|
import net.minecraft.entity.ItemEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.particle.ParticleTypes;
|
||||||
import net.minecraft.util.hit.EntityHitResult;
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
@ -44,9 +44,10 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp
|
||||||
if (timer.getTicksRemaining() <= 0) {
|
if (timer.getTicksRemaining() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
setDirty();
|
|
||||||
target.getOrEmpty(caster.asWorld())
|
target.getOrEmpty(caster.asWorld())
|
||||||
.filter(entity -> entity.distanceTo(caster.asEntity()) > getDrawDropOffRange(caster))
|
.filter(entity -> entity.distanceTo(caster.asEntity()) > getDrawDropOffRange(caster))
|
||||||
.ifPresent(entity -> {
|
.ifPresent(entity -> {
|
||||||
|
@ -59,12 +60,13 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateParticles(Caster<?> source) {
|
public void generateParticles(Caster<?> source) {
|
||||||
double range = getDrawDropOffRange(source) + 10;
|
double range = getDrawDropOffRange(source);
|
||||||
|
Vec3d origin = getOrigin(source);
|
||||||
|
|
||||||
source.spawnParticles(getOrigin(source), new Sphere(false, range), 7, p -> {
|
source.spawnParticles(origin, new Sphere(false, range), 7, p -> {
|
||||||
source.addParticle(
|
source.addParticle(
|
||||||
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, source.asEntity(), 0.4F)
|
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
|
||||||
.withChild(new MagicParticleEffect(getType().getColor())),
|
.withChild(ParticleTypes.AMBIENT_ENTITY_EFFECT),
|
||||||
p,
|
p,
|
||||||
Vec3d.ZERO
|
Vec3d.ZERO
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,12 +11,10 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.entity.*;
|
import com.minelittlepony.unicopia.entity.*;
|
||||||
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
|
||||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
|
||||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||||
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
@ -48,11 +46,11 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
||||||
.with(Trait.POWER, 1)
|
.with(Trait.POWER, 1)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
protected final ParticleHandle particlEffect = new ParticleHandle();
|
|
||||||
|
|
||||||
private final Timer timer;
|
private final Timer timer;
|
||||||
|
|
||||||
private int struggles;
|
private int struggles;
|
||||||
|
|
||||||
|
private float prevRadius;
|
||||||
private float radius;
|
private float radius;
|
||||||
|
|
||||||
protected BubbleSpell(CustomisedSpellType<?> type) {
|
protected BubbleSpell(CustomisedSpellType<?> type) {
|
||||||
|
@ -66,6 +64,10 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getRadius(float tickDelta) {
|
||||||
|
return MathHelper.lerp(tickDelta, prevRadius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Caster<?> source) {
|
public boolean apply(Caster<?> source) {
|
||||||
|
|
||||||
|
@ -95,14 +97,19 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
||||||
public boolean tick(Caster<?> source, Situation situation) {
|
public boolean tick(Caster<?> source, Situation situation) {
|
||||||
|
|
||||||
if (situation == Situation.PROJECTILE) {
|
if (situation == Situation.PROJECTILE) {
|
||||||
|
source.spawnParticles(UParticles.BUBBLE, 2);
|
||||||
source.spawnParticles(ParticleTypes.BUBBLE, 2);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.tick();
|
timer.tick();
|
||||||
|
|
||||||
if (timer.getTicksRemaining() <= 0) {
|
boolean done = timer.getTicksRemaining() <= 0;
|
||||||
|
|
||||||
|
source.spawnParticles(source.getOriginVector().add(0, 1, 0), new Sphere(true, radius * (done ? 0.25F : 0.5F)), done ? 13 : 1, pos -> {
|
||||||
|
source.addParticle(done ? ParticleTypes.BUBBLE_POP : UParticles.BUBBLE, pos, Vec3d.ZERO);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (done) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +123,7 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
||||||
|
|
||||||
source.asEntity().fallDistance = 0;
|
source.asEntity().fallDistance = 0;
|
||||||
|
|
||||||
Vec3d origin = source.getOriginVector();
|
prevRadius = radius;
|
||||||
|
|
||||||
if (source instanceof Pony pony && pony.sneakingChanged() && pony.asEntity().isSneaking()) {
|
if (source instanceof Pony pony && pony.sneakingChanged() && pony.asEntity().isSneaking()) {
|
||||||
setDirty();
|
setDirty();
|
||||||
|
@ -128,18 +135,11 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
particlEffect.update(getUuid(), source, spawner -> {
|
|
||||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, 0xFFFFFF, 0.3F, 0, new Vec3d(0, radius / 2F, 0)), origin, Vec3d.ZERO);
|
|
||||||
}).ifPresent(p -> {
|
|
||||||
p.setAttribute(Attachment.ATTR_RADIUS, radius);
|
|
||||||
});
|
|
||||||
|
|
||||||
return !isDead();
|
return !isDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroyed(Caster<?> source) {
|
protected void onDestroyed(Caster<?> source) {
|
||||||
particlEffect.destroy();
|
|
||||||
if (source.asEntity() instanceof LivingEntity l) {
|
if (source.asEntity() instanceof LivingEntity l) {
|
||||||
MODIFIERS.forEach((attribute, modifier) -> {
|
MODIFIERS.forEach((attribute, modifier) -> {
|
||||||
if (l.getAttributes().hasAttribute(attribute)) {
|
if (l.getAttributes().hasAttribute(attribute)) {
|
||||||
|
|
|
@ -10,11 +10,11 @@ import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
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.particle.SphereParticleEffect;
|
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||||
|
@ -48,7 +48,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
|
|
||||||
private static final Vec3d SPHERE_OFFSET = new Vec3d(0, 2, 0);
|
private static final Vec3d SPHERE_OFFSET = new Vec3d(0, 2, 0);
|
||||||
|
|
||||||
private int age = 0;
|
|
||||||
private float accumulatedMass = 0;
|
private float accumulatedMass = 0;
|
||||||
|
|
||||||
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
||||||
|
@ -80,10 +79,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
age++;
|
if (source.asEntity().age % 20 == 0) {
|
||||||
setDirty();
|
|
||||||
|
|
||||||
if (age % 20 == 0) {
|
|
||||||
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_ADDITIONS, SoundCategory.AMBIENT, 1, 1);
|
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_ADDITIONS, SoundCategory.AMBIENT, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,21 +112,20 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
public void generateParticles(Caster<?> source) {
|
public void generateParticles(Caster<?> source) {
|
||||||
super.generateParticles(source);
|
super.generateParticles(source);
|
||||||
|
|
||||||
float radius = (float)getEventHorizonRadius();
|
if (getEventHorizonRadius() > 0.3) {
|
||||||
|
double range = getDrawDropOffRange(source);
|
||||||
particlEffect.update(getUuid(), source, spawner -> {
|
Vec3d origin = getOrigin(source);
|
||||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, 0x000000, 0.99F, radius, SPHERE_OFFSET), source.getOriginVector(), Vec3d.ZERO);
|
source.spawnParticles(origin, new Sphere(false, range), 1, p -> {
|
||||||
}).ifPresent(p -> {
|
if (!source.asWorld().isAir(BlockPos.ofFloored(p))) {
|
||||||
p.setAttribute(Attachment.ATTR_RADIUS, radius);
|
source.addParticle(
|
||||||
p.setAttribute(Attachment.ATTR_OPACITY, 2F);
|
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
|
||||||
});
|
.withChild(ParticleTypes.CAMPFIRE_SIGNAL_SMOKE),
|
||||||
particlEffect.update(getUuid(), "_ring", source, spawner -> {
|
p,
|
||||||
spawner.addParticle(new SphereParticleEffect(UParticles.DISK, 0xAAAAAA, 0.4F, radius + 1, SPHERE_OFFSET), getOrigin(source), Vec3d.ZERO);
|
Vec3d.ZERO
|
||||||
}).ifPresent(p -> {
|
);
|
||||||
p.setAttribute(Attachment.ATTR_RADIUS, radius * 0F);
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
source.spawnParticles(ParticleTypes.SMOKE, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -162,7 +157,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
applyRadialEffect(source, e, e.getPos().distanceTo(origin), radius);
|
applyRadialEffect(source, e, e.getPos().distanceTo(origin), radius);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setDirty();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,8 +174,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
// 2. max force (at dist 0) is taken from accumulated mass
|
// 2. max force (at dist 0) is taken from accumulated mass
|
||||||
// 3. force reaches 0 at distance of drawDropOffRange
|
// 3. force reaches 0 at distance of drawDropOffRange
|
||||||
|
|
||||||
private double getEventHorizonRadius() {
|
public double getEventHorizonRadius() {
|
||||||
return Math.sqrt(Math.max(0.001, getMass() - 12));
|
return Math.sqrt(Math.max(0.001, getMass() / 3F));
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getAttractiveForce(Caster<?> source, Entity target) {
|
private double getAttractiveForce(Caster<?> source, Entity target) {
|
||||||
|
@ -189,8 +183,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getMass() {
|
private double getMass() {
|
||||||
float pulse = (float)Math.sin(age * 8) / 1F;
|
return Math.min(15, 0.1F + accumulatedMass / 10F);
|
||||||
return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -202,6 +195,11 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
|
|
||||||
if (distance <= getEventHorizonRadius() + 0.5) {
|
if (distance <= getEventHorizonRadius() + 0.5) {
|
||||||
target.setVelocity(target.getVelocity().multiply(distance / (2 * radius)));
|
target.setVelocity(target.getVelocity().multiply(distance / (2 * radius)));
|
||||||
|
if (distance < 1) {
|
||||||
|
target.setVelocity(target.getVelocity().multiply(distance));
|
||||||
|
|
||||||
|
}
|
||||||
|
Living.updateVelocity(target);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
Entity master = source.getMaster();
|
Entity master = source.getMaster();
|
||||||
|
@ -221,13 +219,19 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
|
|
||||||
double massOfTarget = AttractionUtils.getMass(target);
|
double massOfTarget = AttractionUtils.getMass(target);
|
||||||
|
|
||||||
accumulatedMass += massOfTarget;
|
if (!source.isClient() && massOfTarget != 0) {
|
||||||
setDirty();
|
accumulatedMass += massOfTarget;
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
target.damage(source.damageOf(UDamageTypes.GAVITY_WELL_RECOIL, source), Integer.MAX_VALUE);
|
target.damage(source.damageOf(UDamageTypes.GAVITY_WELL_RECOIL, source), Integer.MAX_VALUE);
|
||||||
if (!(target instanceof PlayerEntity)) {
|
if (!(target instanceof PlayerEntity)) {
|
||||||
target.discard();
|
target.discard();
|
||||||
source.asWorld().playSound(null, source.getOrigin(), USounds.ENCHANTMENT_CONSUMPTION_CONSUME, SoundCategory.AMBIENT, 2, 0.02F);
|
source.asWorld().playSound(null, source.getOrigin(), USounds.ENCHANTMENT_CONSUMPTION_CONSUME, SoundCategory.AMBIENT, 2, 0.02F);
|
||||||
}
|
}
|
||||||
|
if (target.isAlive()) {
|
||||||
|
target.damage(source.asEntity().getDamageSources().outOfWorld(), Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
source.subtractEnergyCost(-massOfTarget * 10);
|
source.subtractEnergyCost(-massOfTarget * 10);
|
||||||
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
|
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
|
||||||
|
@ -243,14 +247,12 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
@Override
|
@Override
|
||||||
public void toNBT(NbtCompound compound) {
|
public void toNBT(NbtCompound compound) {
|
||||||
super.toNBT(compound);
|
super.toNBT(compound);
|
||||||
compound.putInt("age", age);
|
|
||||||
compound.putFloat("accumulatedMass", accumulatedMass);
|
compound.putFloat("accumulatedMass", accumulatedMass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
super.fromNBT(compound);
|
super.fromNBT(compound);
|
||||||
age = compound.getInt("age");
|
|
||||||
accumulatedMass = compound.getFloat("accumulatedMass");
|
accumulatedMass = compound.getFloat("accumulatedMass");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.*;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.entity.EntityReference;
|
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
|
||||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||||
|
|
||||||
|
@ -16,7 +14,7 @@ import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.util.hit.EntityHitResult;
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class DisplacementSpell extends AbstractSpell implements HomingSpell, PlaceableSpell.PlacementDelegate, ProjectileDelegate.EntityHitListener {
|
public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener {
|
||||||
|
|
||||||
private final EntityReference<Entity> target = new EntityReference<>();
|
private final EntityReference<Entity> target = new EntityReference<>();
|
||||||
|
|
||||||
|
@ -67,19 +65,6 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pla
|
||||||
originator.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F);
|
originator.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlaced(Caster<?> source, PlaceableSpell parent, CastSpellEntity entity) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePlacement(Caster<?> caster, PlaceableSpell parent) {
|
|
||||||
parent.getParticleEffectAttachment(caster).ifPresent(attachment -> {
|
|
||||||
float r = 3 - (1 - ((ticks + 10) / 20F)) * 3;
|
|
||||||
attachment.setAttribute(Attachment.ATTR_RADIUS, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void teleport(Caster<?> source, Entity entity, Vec3d pos, Vec3d vel) {
|
private void teleport(Caster<?> source, Entity entity, Vec3d pos, Vec3d vel) {
|
||||||
entity.teleport(pos.x, pos.y, pos.z);
|
entity.teleport(pos.x, pos.y, pos.z);
|
||||||
entity.setVelocity(vel);
|
entity.setVelocity(vel);
|
||||||
|
|
|
@ -14,7 +14,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.entity.EntityReference;
|
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||||
import com.minelittlepony.unicopia.particle.*;
|
import com.minelittlepony.unicopia.particle.*;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
|
||||||
import com.minelittlepony.unicopia.server.world.Ether;
|
import com.minelittlepony.unicopia.server.world.Ether;
|
||||||
import com.minelittlepony.unicopia.util.shape.*;
|
import com.minelittlepony.unicopia.util.shape.*;
|
||||||
|
|
||||||
|
@ -177,14 +176,6 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme
|
||||||
entity.setPos(targetPos.x, caster.getY() + 1.5, targetPos.z);
|
entity.setPos(targetPos.x, caster.getY() + 1.5, targetPos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePlacement(Caster<?> source, PlaceableSpell parent) {
|
|
||||||
parent.getParticleEffectAttachment(source).ifPresent(attachment -> {
|
|
||||||
attachment.setAttribute(Attachment.ATTR_RADIUS, 2);
|
|
||||||
attachment.setAttribute(Attachment.ATTR_OPACITY, 0.92F);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroyed(Caster<?> caster) {
|
protected void onDestroyed(Caster<?> caster) {
|
||||||
particleEffect.destroy();
|
particleEffect.destroy();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Affinity;
|
import com.minelittlepony.unicopia.Affinity;
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
@ -10,11 +12,9 @@ import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
||||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
|
@ -30,6 +30,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.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class ShieldSpell extends AbstractSpell {
|
public class ShieldSpell extends AbstractSpell {
|
||||||
|
@ -40,10 +41,14 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
.with(Trait.AIR, 9)
|
.with(Trait.AIR, 9)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
protected final ParticleHandle particlEffect = new ParticleHandle();
|
|
||||||
|
|
||||||
private final TargetSelecter targetSelecter = new TargetSelecter(this);
|
private final TargetSelecter targetSelecter = new TargetSelecter(this);
|
||||||
|
|
||||||
|
private float prevRadius;
|
||||||
|
private float radius;
|
||||||
|
|
||||||
|
private float rangeMultiplier;
|
||||||
|
private float targetRangeMultiplier;
|
||||||
|
|
||||||
protected ShieldSpell(CustomisedSpellType<?> type) {
|
protected ShieldSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
@ -53,33 +58,27 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
return method == CastingMethod.STAFF || getTraits().get(Trait.GENEROSITY) > 0 ? toPlaceable() : this;
|
return method == CastingMethod.STAFF || getTraits().get(Trait.GENEROSITY) > 0 ? toPlaceable() : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroyed(Caster<?> caster) {
|
|
||||||
particlEffect.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Affinity getAffinity() {
|
public Affinity getAffinity() {
|
||||||
return getTraits().get(Trait.DARKNESS) > 0 ? Affinity.BAD : Affinity.GOOD;
|
return getTraits().get(Trait.DARKNESS) > 0 ? Affinity.BAD : Affinity.GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateParticles(Caster<?> source) {
|
protected void generateParticles(Caster<?> source) {
|
||||||
float radius = (float)getDrawDropOffRange(source);
|
|
||||||
Vec3d origin = getOrigin(source);
|
Vec3d origin = getOrigin(source);
|
||||||
|
|
||||||
source.spawnParticles(origin, new Sphere(true, radius), (int)(radius * 6), pos -> {
|
source.spawnParticles(origin, new Sphere(true, radius), (int)(radius * 6), pos -> {
|
||||||
source.addParticle(new MagicParticleEffect(getType().getColor()), pos, Vec3d.ZERO);
|
source.addParticle(new MagicParticleEffect(getType().getColor()), pos, Vec3d.ZERO);
|
||||||
});
|
|
||||||
|
|
||||||
particlEffect.update(getUuid(), source, spawner -> {
|
if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) {
|
||||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, getType().getColor(), 0.3F, radius), origin, Vec3d.ZERO);
|
ParticleUtils.spawnParticle(source.asWorld(), new LightningBoltParticleEffect(true, 3, 2, 0.1F, Optional.empty()), pos, Vec3d.ZERO);
|
||||||
}).ifPresent(p -> {
|
}
|
||||||
p.setAttribute(Attachment.ATTR_RADIUS, radius);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tick(Caster<?> source, Situation situation) {
|
public boolean tick(Caster<?> source, Situation situation) {
|
||||||
|
prevRadius = radius;
|
||||||
|
radius = (float)getDrawDropOffRange(source);
|
||||||
|
|
||||||
if (source.isClient()) {
|
if (source.isClient()) {
|
||||||
generateParticles(source);
|
generateParticles(source);
|
||||||
|
@ -108,20 +107,32 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
|
|
||||||
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
|
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
|
||||||
cost /= knowledge;
|
cost /= knowledge;
|
||||||
cost += getDrawDropOffRange(source) / 10F;
|
cost += radius / 10F;
|
||||||
|
|
||||||
if (!source.subtractEnergyCost(cost)) {
|
if (!source.subtractEnergyCost(cost)) {
|
||||||
setDead();
|
setDead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getRadius(float tickDelta) {
|
||||||
|
return MathHelper.lerp(tickDelta, prevRadius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the maximum radius of the shield. aka The area of effect.
|
* Calculates the maximum radius of the shield. aka The area of effect.
|
||||||
*/
|
*/
|
||||||
public double getDrawDropOffRange(Caster<?> source) {
|
public double getDrawDropOffRange(Caster<?> source) {
|
||||||
float multiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2;
|
targetRangeMultiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2;
|
||||||
|
if (rangeMultiplier < targetRangeMultiplier - 0.1F) {
|
||||||
|
rangeMultiplier += 0.1F;
|
||||||
|
} else if (rangeMultiplier > targetRangeMultiplier + 0.1) {
|
||||||
|
rangeMultiplier -= 0.1F;
|
||||||
|
} else {
|
||||||
|
rangeMultiplier = targetRangeMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER);
|
float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER);
|
||||||
double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / multiplier;
|
double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier;
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +161,7 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long applyEntities(Caster<?> source) {
|
protected long applyEntities(Caster<?> source) {
|
||||||
double radius = getDrawDropOffRange(source);
|
double radius = this.radius;
|
||||||
|
|
||||||
Vec3d origin = getOrigin(source);
|
Vec3d origin = getOrigin(source);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.util.stream.Stream;
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Affine;
|
import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||||
|
@ -29,7 +28,7 @@ public class TargetSelecter {
|
||||||
public Stream<Entity> getEntities(Caster<?> source, double radius, BiPredicate<Caster<?>, Entity> filter) {
|
public Stream<Entity> getEntities(Caster<?> source, double radius, BiPredicate<Caster<?>, Entity> filter) {
|
||||||
targets.values().removeIf(Target::tick);
|
targets.values().removeIf(Target::tick);
|
||||||
return source.findAllEntitiesInRange(radius)
|
return source.findAllEntitiesInRange(radius)
|
||||||
.filter(entity -> entity.isAlive() && !entity.isRemoved() && notOwnerOrFriend(spell, source, entity) && !SpellPredicate.IS_SHIELD_LIKE.isOn(entity))
|
.filter(entity -> entity.isAlive() && !entity.isRemoved() && notOwnerOrFriend(spell, source, entity))
|
||||||
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
|
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
|
||||||
.filter(e -> filter.test(source, e))
|
.filter(e -> filter.test(source, e))
|
||||||
.map(i -> {
|
.map(i -> {
|
||||||
|
@ -57,6 +56,11 @@ public class TargetSelecter {
|
||||||
public static <T extends Entity> boolean isOwnerOrFriend(Affine affine, Caster<?> source, Entity target) {
|
public static <T extends Entity> boolean isOwnerOrFriend(Affine affine, Caster<?> source, Entity target) {
|
||||||
Entity owner = source.getMaster();
|
Entity owner = source.getMaster();
|
||||||
|
|
||||||
|
var equine = Pony.of(target);
|
||||||
|
if (equine.isPresent() && !affine.isFriendlyTogether(equine.get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (affine.isEnemy(source)) {
|
if (affine.isEnemy(source)) {
|
||||||
return FriendshipBraceletItem.isComrade(source, target);
|
return FriendshipBraceletItem.isComrade(source, target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.block.cloud.CloudChestBlock;
|
||||||
import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle;
|
import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle;
|
||||||
import com.minelittlepony.unicopia.client.particle.CloudsEscapingParticle;
|
import com.minelittlepony.unicopia.client.particle.CloudsEscapingParticle;
|
||||||
import com.minelittlepony.unicopia.client.particle.DiskParticle;
|
import com.minelittlepony.unicopia.client.particle.DiskParticle;
|
||||||
|
import com.minelittlepony.unicopia.client.particle.FloatingBubbleParticle;
|
||||||
import com.minelittlepony.unicopia.client.particle.GroundPoundParticle;
|
import com.minelittlepony.unicopia.client.particle.GroundPoundParticle;
|
||||||
import com.minelittlepony.unicopia.client.particle.HealthDrainParticle;
|
import com.minelittlepony.unicopia.client.particle.HealthDrainParticle;
|
||||||
import com.minelittlepony.unicopia.client.particle.LightningBoltParticle;
|
import com.minelittlepony.unicopia.client.particle.LightningBoltParticle;
|
||||||
|
@ -65,6 +66,7 @@ public interface URenderers {
|
||||||
static void bootstrap() {
|
static void bootstrap() {
|
||||||
ParticleFactoryRegistry.getInstance().register(UParticles.UNICORN_MAGIC, createFactory(MagicParticle::new));
|
ParticleFactoryRegistry.getInstance().register(UParticles.UNICORN_MAGIC, createFactory(MagicParticle::new));
|
||||||
ParticleFactoryRegistry.getInstance().register(UParticles.CHANGELING_MAGIC, createFactory(ChangelingMagicParticle::new));
|
ParticleFactoryRegistry.getInstance().register(UParticles.CHANGELING_MAGIC, createFactory(ChangelingMagicParticle::new));
|
||||||
|
ParticleFactoryRegistry.getInstance().register(UParticles.BUBBLE, createFactory(FloatingBubbleParticle::new));
|
||||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new));
|
ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new));
|
||||||
ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create));
|
ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create));
|
||||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
|
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.minelittlepony.unicopia.*;
|
||||||
import com.minelittlepony.unicopia.ability.*;
|
import com.minelittlepony.unicopia.ability.*;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
|
import com.minelittlepony.unicopia.client.render.spell.DarkVortexSpellRenderer;
|
||||||
import com.minelittlepony.unicopia.client.sound.*;
|
import com.minelittlepony.unicopia.client.sound.*;
|
||||||
import com.minelittlepony.unicopia.entity.ItemTracker;
|
import com.minelittlepony.unicopia.entity.ItemTracker;
|
||||||
import com.minelittlepony.unicopia.entity.effect.EffectUtils;
|
import com.minelittlepony.unicopia.entity.effect.EffectUtils;
|
||||||
|
@ -193,6 +195,19 @@ public class UHud {
|
||||||
|
|
||||||
protected void renderViewEffects(Pony pony, DrawContext context, int scaledWidth, int scaledHeight, float tickDelta) {
|
protected void renderViewEffects(Pony pony, DrawContext context, int scaledWidth, int scaledHeight, float tickDelta) {
|
||||||
|
|
||||||
|
float vortexDistortion = DarkVortexSpellRenderer.getCameraDistortion();
|
||||||
|
|
||||||
|
if (vortexDistortion > 20) {
|
||||||
|
context.fill(RenderLayers.getEndPortal(), 0, 0, scaledWidth, scaledHeight, 0);
|
||||||
|
context.getMatrices().push();
|
||||||
|
context.getMatrices().translate(scaledWidth / 2, scaledHeight / 2, 0);
|
||||||
|
DrawableUtil.drawArc(context.getMatrices(), 0, 20, 0, MathHelper.TAU, 0x000000FF, false);
|
||||||
|
context.getMatrices().pop();
|
||||||
|
return;
|
||||||
|
} else if (vortexDistortion > 0) {
|
||||||
|
context.fill(0, 0, scaledWidth, scaledHeight, (int)((vortexDistortion / 20F) * 255) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
||||||
|
|
||||||
ItemStack glasses = GlassesItem.getForEntity(client.player);
|
ItemStack glasses = GlassesItem.getForEntity(client.player);
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class CloudsEscapingParticle extends GroundPoundParticle {
|
||||||
);
|
);
|
||||||
|
|
||||||
double columnHeight = 1 + age / 30;
|
double columnHeight = 1 + age / 30;
|
||||||
new Sphere(true, columnHeight, 1, 1, 1)
|
new Sphere(true, columnHeight)
|
||||||
.translate(center)
|
.translate(center)
|
||||||
.randomPoints(random)
|
.randomPoints(random)
|
||||||
.forEach(point -> {
|
.forEach(point -> {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.minelittlepony.unicopia.client.particle;
|
||||||
|
|
||||||
|
import net.minecraft.client.particle.ParticleTextureSheet;
|
||||||
|
import net.minecraft.client.particle.SpriteBillboardParticle;
|
||||||
|
import net.minecraft.client.particle.SpriteProvider;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.particle.ParticleEffect;
|
||||||
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
|
||||||
|
public class FloatingBubbleParticle extends SpriteBillboardParticle {
|
||||||
|
public FloatingBubbleParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld clientWorld, double x, double y, double z, double dX, double dY, double dZ) {
|
||||||
|
super(clientWorld, x, y, z, dX, dY, dZ);
|
||||||
|
setSprite(provider);
|
||||||
|
scale((float)clientWorld.random.nextTriangular(1F, 0.5F));
|
||||||
|
this.velocityX *= -0.1F;
|
||||||
|
this.velocityY *= -0.1F;
|
||||||
|
this.velocityZ *= -0.1F;
|
||||||
|
this.maxAge *= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParticleTextureSheet getType() {
|
||||||
|
return ParticleTextureSheet.PARTICLE_SHEET_OPAQUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markDead() {
|
||||||
|
super.markDead();
|
||||||
|
world.addParticle(ParticleTypes.BUBBLE_POP, x, y, z, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,6 @@ public abstract class OrientedBillboardParticle extends AbstractBillboardParticl
|
||||||
|
|
||||||
fixed = effect.fixed();
|
fixed = effect.fixed();
|
||||||
if (fixed) {
|
if (fixed) {
|
||||||
// Was hamiltonianProduct (CHECK THIS!!)
|
|
||||||
rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees(effect.pitch()));
|
rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees(effect.pitch()));
|
||||||
rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - effect.yaw()));
|
rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - effect.yaw()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class RunesParticle extends OrientedBillboardParticle implements Attachment {
|
public class RunesParticle extends OrientedBillboardParticle implements Attachment {
|
||||||
|
|
||||||
private static final Identifier[] TEXTURES = new Identifier[] {
|
private static final Identifier[] TEXTURES = new Identifier[] {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.client.FirstPersonRendererOverrides.ArmRenderer;
|
import com.minelittlepony.unicopia.client.FirstPersonRendererOverrides.ArmRenderer;
|
||||||
|
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate;
|
||||||
import com.minelittlepony.unicopia.client.render.spell.SpellEffectsRenderDispatcher;
|
import com.minelittlepony.unicopia.client.render.spell.SpellEffectsRenderDispatcher;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
@ -13,14 +14,14 @@ import net.minecraft.client.model.ModelPart;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
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.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
|
||||||
public class AccessoryFeatureRenderer<
|
public class AccessoryFeatureRenderer<
|
||||||
T extends LivingEntity,
|
T extends LivingEntity,
|
||||||
M extends BipedEntityModel<T>> extends FeatureRenderer<T, M> {
|
M extends EntityModel<T>> extends FeatureRenderer<T, M> {
|
||||||
|
|
||||||
private static final List<FeatureFactory<?>> REGISTRY = new ArrayList<>();
|
private static final List<FeatureFactory<?>> REGISTRY = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -40,6 +41,10 @@ public class AccessoryFeatureRenderer<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, T entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, T entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
if (MineLPDelegate.getInstance().getRace(entity).isEquine()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
features.forEach(feature -> feature.render(matrices, vertexConsumers, light, entity, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch));
|
features.forEach(feature -> feature.render(matrices, vertexConsumers, light, entity, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch));
|
||||||
|
|
||||||
Caster.of(entity).ifPresent(caster -> {
|
Caster.of(entity).ifPresent(caster -> {
|
||||||
|
@ -60,7 +65,7 @@ public class AccessoryFeatureRenderer<
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface FeatureFactory<T extends LivingEntity> {
|
public interface FeatureFactory<T extends LivingEntity> {
|
||||||
Feature<T> create(FeatureRendererContext<T, ? extends BipedEntityModel<T>> context);
|
Feature<T> create(FeatureRendererContext<T, ? extends EntityModel<T>> context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Feature<T extends LivingEntity> {
|
public interface Feature<T extends LivingEntity> {
|
||||||
|
@ -75,11 +80,11 @@ public class AccessoryFeatureRenderer<
|
||||||
|
|
||||||
public interface FeatureRoot<
|
public interface FeatureRoot<
|
||||||
T extends LivingEntity,
|
T extends LivingEntity,
|
||||||
M extends BipedEntityModel<T>> {
|
M extends EntityModel<T>> {
|
||||||
AccessoryFeatureRenderer<T, M> getAccessories();
|
AccessoryFeatureRenderer<T, M> getAccessories();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Nullable
|
@Nullable
|
||||||
static <T extends LivingEntity, M extends BipedEntityModel<T>> FeatureRoot<T, M> of(T entity) {
|
static <T extends LivingEntity, M extends EntityModel<T>> FeatureRoot<T, M> of(T entity) {
|
||||||
var renderer = MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity);
|
var renderer = MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity);
|
||||||
if (renderer instanceof FeatureRoot) {
|
if (renderer instanceof FeatureRoot) {
|
||||||
return (FeatureRoot<T, M>)renderer;
|
return (FeatureRoot<T, M>)renderer;
|
||||||
|
|
|
@ -39,6 +39,15 @@ public final class RenderLayers extends RenderLayer {
|
||||||
.target(TRANSLUCENT_TARGET)
|
.target(TRANSLUCENT_TARGET)
|
||||||
.build(false));
|
.build(false));
|
||||||
|
|
||||||
|
private static final RenderLayer MAGIC_SHIELD = of("magic_shield", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL,
|
||||||
|
VertexFormat.DrawMode.QUADS, 256, true, true, MultiPhaseParameters.builder()
|
||||||
|
.program(COLOR_PROGRAM)
|
||||||
|
.transparency(TRANSLUCENT_TRANSPARENCY)
|
||||||
|
.target(TRANSLUCENT_TARGET)
|
||||||
|
.cull(DISABLE_CULLING)
|
||||||
|
.writeMaskState(COLOR_MASK)
|
||||||
|
.build(false));
|
||||||
|
|
||||||
private static final Function<Integer, RenderLayer> MAGIC_COLORIN_FUNC = Util.memoize(color -> {
|
private static final Function<Integer, RenderLayer> MAGIC_COLORIN_FUNC = Util.memoize(color -> {
|
||||||
return of("magic_colored_" + color,
|
return of("magic_colored_" + color,
|
||||||
VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL,
|
VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL,
|
||||||
|
@ -75,6 +84,10 @@ public final class RenderLayers extends RenderLayer {
|
||||||
return MAGIC_NO_COLOR;
|
return MAGIC_NO_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RenderLayer getMagicShield() {
|
||||||
|
return MAGIC_SHIELD;
|
||||||
|
}
|
||||||
|
|
||||||
public static RenderLayer getMagicColored() {
|
public static RenderLayer getMagicColored() {
|
||||||
return MAGIC_COLORED;
|
return MAGIC_COLORED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.minelittlepony.unicopia.client.render;
|
package com.minelittlepony.unicopia.client.render;
|
||||||
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ import net.minecraft.client.render.VertexFormats;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
|
||||||
public class RenderUtil {
|
public class RenderUtil {
|
||||||
private static final Vector4f TEMP_VECTOR = new Vector4f();
|
public static final Vector4f TEMP_VECTOR = new Vector4f();
|
||||||
public static final Vertex[] UNIT_FACE = new Vertex[] {
|
public static final Vertex[] UNIT_FACE = new Vertex[] {
|
||||||
new Vertex(new Vector3f(0, 0, 0), 1, 1),
|
new Vertex(new Vector3f(0, 0, 0), 1, 1),
|
||||||
new Vertex(new Vector3f(0, 1, 0), 1, 0),
|
new Vertex(new Vector3f(0, 1, 0), 1, 0),
|
||||||
|
@ -21,21 +20,18 @@ public class RenderUtil {
|
||||||
|
|
||||||
public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) {
|
public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) {
|
||||||
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
||||||
|
|
||||||
Vertex[] UNIT_FACE = new Vertex[] {
|
|
||||||
new Vertex(new Vector3f(0, 0, 0), 1, 1),
|
|
||||||
new Vertex(new Vector3f(0, 1, 0), 1, 0),
|
|
||||||
new Vertex(new Vector3f(1, 1, 0), 0, 0),
|
|
||||||
new Vertex(new Vector3f(1, 0, 0), 0, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix4f transformation = matrices.peek().getPositionMatrix();
|
|
||||||
for (Vertex vertex : UNIT_FACE) {
|
for (Vertex vertex : UNIT_FACE) {
|
||||||
transformation.transform(TEMP_VECTOR.set(vertex.position(), 1));
|
Vector4f position = vertex.position(matrices);
|
||||||
buffer.vertex(TEMP_VECTOR.x, TEMP_VECTOR.y, TEMP_VECTOR.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next();
|
buffer.vertex(position.x, position.y, position.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next();
|
||||||
}
|
}
|
||||||
te.draw();
|
te.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
record Vertex(Vector3f position, float u, float v) {}
|
public record Vertex(Vector3f position, float u, float v) {
|
||||||
|
|
||||||
|
public Vector4f position(MatrixStack matrices) {
|
||||||
|
matrices.peek().getPositionMatrix().transform(TEMP_VECTOR.set(position, 1));
|
||||||
|
return TEMP_VECTOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@ import net.minecraft.screen.PlayerScreenHandler;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
||||||
private final SpellEffectsRenderDispatcher spellRenderDispatcher = new SpellEffectsRenderDispatcher();
|
|
||||||
|
|
||||||
public CastSpellEntityRenderer(EntityRendererFactory.Context ctx) {
|
public CastSpellEntityRenderer(EntityRendererFactory.Context ctx) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +22,7 @@ public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(CastSpellEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
|
public void render(CastSpellEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
|
||||||
spellRenderDispatcher.render(matrices, vertexConsumers, light, entity, 0, 0, tickDelta, getAnimationProgress(entity, tickDelta), yaw, 0);
|
SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertexConsumers, light, entity, 0, 0, tickDelta, getAnimationProgress(entity, tickDelta), yaw, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getAnimationProgress(CastSpellEntity entity, float tickDelta) {
|
protected float getAnimationProgress(CastSpellEntity entity, float tickDelta) {
|
||||||
|
|
|
@ -3,38 +3,37 @@ package com.minelittlepony.unicopia.client.render.model;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Vector3f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
||||||
|
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
|
||||||
public class BakedModel {
|
public class BakedModel {
|
||||||
private static final Vector4f drawVert = new Vector4f();
|
protected final List<RenderUtil.Vertex> vertices = new ArrayList<>();
|
||||||
|
|
||||||
protected final List<Vertex> vertices = new ArrayList<>();
|
|
||||||
|
|
||||||
protected void addVertex(Vector4f vertex) {
|
protected void addVertex(Vector4f vertex) {
|
||||||
addVertex(vertex.x, vertex.y, vertex.z, 0, 0);
|
addVertex(vertex.x, vertex.y, vertex.z, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addVertex(float x, float y, float z, float u, float v) {
|
protected void addVertex(float x, float y, float z, float u, float v) {
|
||||||
vertices.add(new Vertex(x, y, z, u, v));
|
vertices.add(new RenderUtil.Vertex(new Vector3f(x, y, z), u, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void render(MatrixStack matrices, VertexConsumer vertexWriter, int light, int overlay, float scale, float r, float g, float b, float a) {
|
public final void render(MatrixStack matrices, VertexConsumer buffer, int light, int overlay, float scale, float r, float g, float b, float a) {
|
||||||
scale = Math.abs(scale);
|
scale = Math.abs(scale);
|
||||||
if (scale < 0.001F) {
|
if (scale < 0.001F) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4f model = matrices.peek().getPositionMatrix();
|
matrices.push();
|
||||||
for (Vertex vertex : vertices) {
|
matrices.scale(scale, scale, scale);
|
||||||
drawVert.set(vertex.x() * scale, vertex.y() * scale, vertex.z() * scale, 1);
|
for (RenderUtil.Vertex vertex : vertices) {
|
||||||
drawVert.mul(model);
|
Vector4f pos = vertex.position(matrices);
|
||||||
vertexWriter.vertex(drawVert.x, drawVert.y, drawVert.z, r, g, b, a, vertex.u(), vertex.v(), overlay, light, 0, 0, 0);
|
buffer.vertex(pos.x, pos.y, pos.z, r, g, b, a, vertex.u(), vertex.v(), overlay, light, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
record Vertex(float x, float y, float z, float u, float v) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.model;
|
||||||
|
|
||||||
|
public class PlaneModel extends BakedModel {
|
||||||
|
public static final PlaneModel INSTANCE = new PlaneModel();
|
||||||
|
|
||||||
|
private PlaneModel() {
|
||||||
|
addVertex(-1, -1, 0, 0, 0);
|
||||||
|
addVertex(-1, 1, 0, 1, 0);
|
||||||
|
addVertex( 1, 1, 0, 1, 1);
|
||||||
|
addVertex( 1, -1, 0, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.BubbleSpell;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
|
||||||
|
public class BubbleSpellRenderer implements SpellRenderer<BubbleSpell> {
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, BubbleSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
matrices.push();
|
||||||
|
double height = caster.asEntity().getEyeY() - caster.getOriginVector().y;
|
||||||
|
matrices.translate(0, height * 0.5F, 0);
|
||||||
|
|
||||||
|
float radius = spell.getRadius(tickDelta) * 0.7F;
|
||||||
|
|
||||||
|
VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicNoColor());
|
||||||
|
|
||||||
|
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-45));
|
||||||
|
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(45 + cameraEntity.getYaw(tickDelta)));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
|
||||||
|
|
||||||
|
new SphereModel(40, 40, DrawableUtil.PI * 0.25F).render(matrices, buffer, light, 0, radius - 0.1F, 0.9F, 0.9F, 1, 0.3F);
|
||||||
|
matrices.pop();
|
||||||
|
|
||||||
|
SphereModel.SPHERE.render(matrices, buffer, light, 0, radius, 0.9F, 0.9F, 1, 0.25F);
|
||||||
|
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.DarkVortexSpell;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
|
||||||
|
public class DarkVortexSpellRenderer implements SpellRenderer<DarkVortexSpell> {
|
||||||
|
|
||||||
|
private static final Identifier ACCRETION_DISK_TEXTURE = Unicopia.id("textures/spells/dark_vortex/accretion_disk.png");
|
||||||
|
|
||||||
|
private static float cameraDistortion;
|
||||||
|
|
||||||
|
public static float getCameraDistortion() {
|
||||||
|
cameraDistortion *= 0.9F;
|
||||||
|
cameraDistortion = MathHelper.clamp(cameraDistortion, 0, 80);
|
||||||
|
return cameraDistortion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, DarkVortexSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
|
||||||
|
|
||||||
|
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
|
||||||
|
|
||||||
|
float radius = (float)spell.getEventHorizonRadius();
|
||||||
|
float absDistance = (float)cameraEntity.getEyePos().distanceTo(caster.getOriginVector().add(0, 2, 0));
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
matrices.translate(0, 2 + radius, 0);
|
||||||
|
|
||||||
|
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, Math.min(radius * 0.6F, absDistance * 0.1F), 0, 0, 0, 1);
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
|
||||||
|
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
|
||||||
|
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + cameraEntity.getYaw(tickDelta)));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
|
||||||
|
|
||||||
|
matrices.scale(0.7F, 1, 1);
|
||||||
|
|
||||||
|
|
||||||
|
float distance = 1F / MathHelper.clamp((absDistance / (radius * 4)), 0.0000001F, 1);
|
||||||
|
distance *= distance;
|
||||||
|
if (absDistance < radius * 4) {
|
||||||
|
cameraDistortion += distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.scale(distance, distance, distance);
|
||||||
|
|
||||||
|
if (absDistance > radius) {
|
||||||
|
matrices.push();
|
||||||
|
matrices.translate(0, -0.1F, 0);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
matrices.scale(1, 1, 0.796F);
|
||||||
|
float brightness = i / 10F;
|
||||||
|
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicNoColor()), light, 1, radius * (1 + (0.25F * i)) * 0.7F, brightness, brightness, brightness, 0.2F);
|
||||||
|
}
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getEndPortal()), light, 1, radius * 0.5F, 1, 0.5F, 0, 1);
|
||||||
|
|
||||||
|
if (radius > 0.3F && absDistance > radius) {
|
||||||
|
radius *= 3 + radius;
|
||||||
|
|
||||||
|
matrices.scale(radius, radius, radius);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(animationProgress * 168));
|
||||||
|
|
||||||
|
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(ACCRETION_DISK_TEXTURE));
|
||||||
|
|
||||||
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
matrices.scale(0.5F, 0.5F, 0.5F);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
|
||||||
|
|
||||||
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||||
|
matrices.pop();
|
||||||
|
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(45));
|
||||||
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||||
|
}
|
||||||
|
matrices.pop();
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
|
import com.minelittlepony.common.util.Color;
|
||||||
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
|
||||||
|
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||||
|
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
|
||||||
|
public class PlacedSpellRenderer implements SpellRenderer<PlaceableSpell> {
|
||||||
|
private static final Identifier[] TEXTURES = new Identifier[] {
|
||||||
|
Unicopia.id("textures/particles/runes_0.png"),
|
||||||
|
Unicopia.id("textures/particles/runes_1.png"),
|
||||||
|
Unicopia.id("textures/particles/runes_2.png"),
|
||||||
|
Unicopia.id("textures/particles/runes_3.png"),
|
||||||
|
Unicopia.id("textures/particles/runes_4.png"),
|
||||||
|
Unicopia.id("textures/particles/runes_5.png")
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, PlaceableSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
|
||||||
|
if (!(caster.asEntity() instanceof CastSpellEntity)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Spell delegate : spell.getDelegates()) {
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
matrices.translate(0, 0.001, 0);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(spell.pitch));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90 - spell.yaw));
|
||||||
|
float scale = (spell.getAge(tickDelta) / 25F) * 3;
|
||||||
|
matrices.scale(scale, scale, scale);
|
||||||
|
|
||||||
|
float angle = (animationProgress / 9F) % 360;
|
||||||
|
|
||||||
|
int color = delegate.getType().getColor();
|
||||||
|
|
||||||
|
float red = Color.r(color);
|
||||||
|
float green = Color.g(color);
|
||||||
|
float blue = Color.b(color);
|
||||||
|
|
||||||
|
for (int i = 0; i < TEXTURES.length; i++) {
|
||||||
|
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(TEXTURES[i]));
|
||||||
|
|
||||||
|
for (int dim = 0; dim < 3; dim++) {
|
||||||
|
float ringSpeed = (i % 2 == 0 ? i : -1) * i;
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angle * ringSpeed));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angle * ringSpeed * dim));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(angle * ringSpeed * dim));
|
||||||
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, red, green, blue, scale / ((float)(dim * 3) + 1));
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.pop();
|
||||||
|
|
||||||
|
SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertices, delegate, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
|
import com.minelittlepony.common.util.Color;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.ShieldSpell;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||||
|
import com.minelittlepony.unicopia.util.ColorHelper;
|
||||||
|
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
public class ShieldSpellRenderer implements SpellRenderer<ShieldSpell> {
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, ShieldSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
matrices.push();
|
||||||
|
double height = caster.asEntity().getEyeY() - caster.getOriginVector().y;
|
||||||
|
matrices.translate(0, height, 0);
|
||||||
|
|
||||||
|
int color = ColorHelper.lerp(caster.getCorruption().getScaled(1) * (tickDelta / (1 + caster.asWorld().random.nextFloat())), spell.getType().getColor(), 0xFF000);
|
||||||
|
float[] colors = ColorHelper.changeSaturation(Color.r(color), Color.g(color), Color.b(color), 4);
|
||||||
|
float radius = 0.35F + spell.getRadius(tickDelta) + MathHelper.sin(animationProgress / 30F) * 0.01F;
|
||||||
|
|
||||||
|
VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicShield());
|
||||||
|
|
||||||
|
float thickness = 0.02F * MathHelper.sin(animationProgress / 30F);
|
||||||
|
float alpha = 1 - Math.abs(MathHelper.sin(animationProgress / 20F)) * 0.2F;
|
||||||
|
SphereModel.SPHERE.render(matrices, buffer, light, 1, radius + thickness, colors[0], colors[1], colors[2], alpha * 0.08F);
|
||||||
|
SphereModel.SPHERE.render(matrices, buffer, light, 1, radius - thickness, colors[0], colors[1], colors[2], alpha * 0.05F);
|
||||||
|
SphereModel.SPHERE.render(matrices, buffer, light, 1, radius + thickness * 2, colors[0], colors[1], colors[2], alpha * 0.05F);
|
||||||
|
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,12 +8,18 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||||
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
|
import com.minelittlepony.unicopia.util.ColorHelper;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
@ -22,6 +28,7 @@ import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.WorldRenderer;
|
import net.minecraft.client.render.WorldRenderer;
|
||||||
|
import net.minecraft.client.render.model.json.ModelTransformationMode;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.resource.ResourceManager;
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
@ -31,6 +38,7 @@ import net.minecraft.util.Colors;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.Box;
|
import net.minecraft.util.math.Box;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.RotationAxis;
|
import net.minecraft.util.math.RotationAxis;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
@ -43,10 +51,19 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
||||||
REGISTRY.put(type, rendererFactory);
|
REGISTRY.put(type, rendererFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
register(SpellType.PLACED_SPELL, PlacedSpellRenderer::new);
|
||||||
|
register(SpellType.SHIELD, ShieldSpellRenderer::new);
|
||||||
|
register(SpellType.DARK_VORTEX, DarkVortexSpellRenderer::new);
|
||||||
|
register(SpellType.BUBBLE, BubbleSpellRenderer::new);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Map<SpellType<?>, SpellRenderer<?>> renderers = Map.of();
|
private Map<SpellType<?>, SpellRenderer<?>> renderers = Map.of();
|
||||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
|
||||||
|
private SpellEffectsRenderDispatcher() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier getFabricId() {
|
public Identifier getFabricId() {
|
||||||
return ID;
|
return ID;
|
||||||
|
@ -57,12 +74,23 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
||||||
return (SpellRenderer<S>)renderers.get(spell.getType());
|
return (SpellRenderer<S>)renderers.get(spell.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
var renderer = getRenderer(spell);
|
||||||
|
|
||||||
|
if (renderer != null) {
|
||||||
|
client.getBufferBuilders().getEntityVertexConsumers().draw();
|
||||||
|
|
||||||
|
renderer.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||||
|
|
||||||
|
if (EquinePredicates.IS_CASTER.test(client.player)) {
|
||||||
|
renderGemstone(matrices, vertices, spell, caster, light, tickDelta, animationProgress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, Caster<?> caster, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, Caster<?> caster, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
caster.getSpellSlot().forEach(spell -> {
|
caster.getSpellSlot().forEach(spell -> {
|
||||||
var renderer = getRenderer(spell);
|
render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||||
if (renderer != null) {
|
|
||||||
renderer.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
|
||||||
}
|
|
||||||
return Operation.SKIP;
|
return Operation.SKIP;
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
@ -77,6 +105,38 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
||||||
renderers = REGISTRY.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().create()));
|
renderers = REGISTRY.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().create()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster<?> caster, int light, float tickDelta, float animationProgress) {
|
||||||
|
matrices.push();
|
||||||
|
|
||||||
|
if (!(caster.asEntity() instanceof MagicProjectileEntity)) {
|
||||||
|
|
||||||
|
float y = -caster.asEntity().getHeight();
|
||||||
|
if (caster.asEntity() instanceof CastSpellEntity) {
|
||||||
|
y = 1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.translate(0, y + MathHelper.sin(animationProgress / 3F) * 0.2F, 0);
|
||||||
|
matrices.push();
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(animationProgress));
|
||||||
|
|
||||||
|
client.getItemRenderer().renderItem(spell.getType().withTraits(spell.getTraits()).getDefaultStack(), ModelTransformationMode.FIXED, light, 0, matrices, vertices, caster.asWorld(), 0);
|
||||||
|
matrices.pop();
|
||||||
|
|
||||||
|
if (spell instanceof TimedSpell timed && spell.getType() != SpellType.DARK_VORTEX) {
|
||||||
|
matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert());
|
||||||
|
float radius = 0.6F;
|
||||||
|
float timeRemaining = timed.getTimer().getPercentTimeRemaining(tickDelta);
|
||||||
|
|
||||||
|
DrawableUtil.drawArc(matrices, radius, radius + 0.3F, 0, DrawableUtil.TAU * timeRemaining,
|
||||||
|
ColorHelper.lerp(MathHelper.clamp(timeRemaining * 4, 0, 1), 0xFF0000FF, 0xFFFFFFFF),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
|
||||||
private void renderSpellDebugInfo(MatrixStack matrices, VertexConsumerProvider vertices, Caster<?> caster, int light) {
|
private void renderSpellDebugInfo(MatrixStack matrices, VertexConsumerProvider vertices, Caster<?> caster, int light) {
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.multiply(client.getEntityRenderDispatcher().getRotation());
|
matrices.multiply(client.getEntityRenderDispatcher().getRotation());
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
|
||||||
|
|
||||||
public CastSpellEntity(EntityType<?> type, World world) {
|
public CastSpellEntity(EntityType<?> type, World world) {
|
||||||
super(type, world);
|
super(type, world);
|
||||||
|
ignoreCameraFrustum = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Optional;
|
||||||
import com.minelittlepony.common.util.animation.MotionCompositor;
|
import com.minelittlepony.common.util.animation.MotionCompositor;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
|
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
|
||||||
|
import com.minelittlepony.unicopia.client.render.spell.DarkVortexSpellRenderer;
|
||||||
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ public class PlayerCamera extends MotionCompositor {
|
||||||
public double calculateFieldOfView(double fov) {
|
public double calculateFieldOfView(double fov) {
|
||||||
fov += player.getMagicalReserves().getExertion().get() / 5F;
|
fov += player.getMagicalReserves().getExertion().get() / 5F;
|
||||||
fov += getEnergyAddition();
|
fov += getEnergyAddition();
|
||||||
|
fov += DarkVortexSpellRenderer.getCameraDistortion() * 2.5F;
|
||||||
|
|
||||||
return fov;
|
return fov;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class FriendshipBraceletItem extends WearableItem implements DyeableItem,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EquipmentSlot getSlotType(ItemStack stack) {
|
public EquipmentSlot getSlotType(ItemStack stack) {
|
||||||
return isSigned(stack) ? EquipmentSlot.CHEST : super.getSlotType();
|
return isSigned(stack) ? EquipmentSlot.CHEST : super.getSlotType(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSignature(ItemStack stack, PlayerEntity player) {
|
private boolean checkSignature(ItemStack stack, PlayerEntity player) {
|
||||||
|
|
|
@ -49,6 +49,7 @@ public abstract class WearableItem extends Item implements Equipment {
|
||||||
return ArmorMaterials.LEATHER.getEquipSound();
|
return ArmorMaterials.LEATHER.getEquipSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public final EquipmentSlot getSlotType() {
|
public final EquipmentSlot getSlotType() {
|
||||||
return getSlotType(getDefaultStack());
|
return getSlotType(getDefaultStack());
|
||||||
|
|
|
@ -1,19 +1,9 @@
|
||||||
package com.minelittlepony.unicopia.mixin.client;
|
package com.minelittlepony.unicopia.mixin.client;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
|
||||||
import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer;
|
import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer;
|
||||||
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
|
||||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
import net.minecraft.client.render.model.BakedModelManager;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
|
||||||
@Mixin(ArmorFeatureRenderer.class)
|
@Mixin(ArmorFeatureRenderer.class)
|
||||||
|
@ -21,13 +11,13 @@ abstract class MixinArmorFeatureRenderer<
|
||||||
T extends LivingEntity,
|
T extends LivingEntity,
|
||||||
M extends BipedEntityModel<T>,
|
M extends BipedEntityModel<T>,
|
||||||
A extends BipedEntityModel<T>>
|
A extends BipedEntityModel<T>>
|
||||||
extends FeatureRenderer<T, M> implements AccessoryFeatureRenderer.FeatureRoot<T, M> {
|
extends FeatureRenderer<T, M>/* implements AccessoryFeatureRenderer.FeatureRoot<T, M>*/ {
|
||||||
|
|
||||||
private AccessoryFeatureRenderer<T, M> accessories;
|
//private AccessoryFeatureRenderer<T, M> accessories;
|
||||||
|
|
||||||
MixinArmorFeatureRenderer() { super(null); }
|
MixinArmorFeatureRenderer() { super(null); }
|
||||||
|
|
||||||
@Override
|
/*@Override
|
||||||
public AccessoryFeatureRenderer<T, M> getAccessories() {
|
public AccessoryFeatureRenderer<T, M> getAccessories() {
|
||||||
return accessories;
|
return accessories;
|
||||||
}
|
}
|
||||||
|
@ -40,5 +30,5 @@ abstract class MixinArmorFeatureRenderer<
|
||||||
@Inject(method = "render", at = @At("RETURN"))
|
@Inject(method = "render", at = @At("RETURN"))
|
||||||
private void onRender(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, T entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch, CallbackInfo info) {
|
private void onRender(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, T entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch, CallbackInfo info) {
|
||||||
getAccessories().render(stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch);
|
getAccessories().render(stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
package com.minelittlepony.unicopia.mixin.client;
|
package com.minelittlepony.unicopia.mixin.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
||||||
import com.minelittlepony.unicopia.client.render.AnimalPoser;
|
import com.minelittlepony.unicopia.client.render.AnimalPoser;
|
||||||
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
||||||
|
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer.FeatureRoot;
|
||||||
|
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.entity.EntityRenderer;
|
import net.minecraft.client.render.entity.EntityRenderer;
|
||||||
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||||
|
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
import net.minecraft.client.render.entity.model.EntityModel;
|
import net.minecraft.client.render.entity.model.EntityModel;
|
||||||
|
@ -21,8 +29,31 @@ import net.minecraft.entity.mob.MobEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
|
||||||
@Mixin(LivingEntityRenderer.class)
|
@Mixin(LivingEntityRenderer.class)
|
||||||
abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends EntityModel<T>> extends EntityRenderer<T> implements FeatureRendererContext<T, M> {
|
abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends EntityModel<T>> extends EntityRenderer<T>
|
||||||
|
implements FeatureRendererContext<T, M>, FeatureRoot<T, M> {
|
||||||
|
@Shadow
|
||||||
|
private @Final List<FeatureRenderer<T, M>> features;
|
||||||
|
|
||||||
MixinLivingEntityRenderer() { super(null); }
|
MixinLivingEntityRenderer() { super(null); }
|
||||||
|
@Nullable
|
||||||
|
private AccessoryFeatureRenderer<T, M> accessories;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public AccessoryFeatureRenderer<T, M> getAccessories() {
|
||||||
|
if (accessories == null) {
|
||||||
|
accessories = features.stream()
|
||||||
|
.filter(a -> a instanceof FeatureRoot)
|
||||||
|
.map(a -> ((FeatureRoot<T, M>)a).getAccessories())
|
||||||
|
.findFirst()
|
||||||
|
.orElseGet(() -> {
|
||||||
|
var feature = new AccessoryFeatureRenderer<>(this);
|
||||||
|
features.add(feature);
|
||||||
|
return feature;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return accessories;
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "render",
|
@Inject(method = "render",
|
||||||
at = @At(
|
at = @At(
|
||||||
|
@ -36,6 +67,7 @@ abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends Entit
|
||||||
VertexConsumerProvider vertices,
|
VertexConsumerProvider vertices,
|
||||||
int light,
|
int light,
|
||||||
CallbackInfo into) {
|
CallbackInfo into) {
|
||||||
|
getAccessories();
|
||||||
if (entity instanceof PlayerEntity player) {
|
if (entity instanceof PlayerEntity player) {
|
||||||
PlayerPoser.INSTANCE.applyPosing(matrices, player, (BipedEntityModel<?>)getModel(), PlayerPoser.Context.THIRD_PERSON);
|
PlayerPoser.INSTANCE.applyPosing(matrices, player, (BipedEntityModel<?>)getModel(), PlayerPoser.Context.THIRD_PERSON);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package com.minelittlepony.unicopia.mixin.client;
|
package com.minelittlepony.unicopia.mixin.client;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
|
||||||
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
||||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer.FeatureRoot;
|
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer.FeatureRoot;
|
||||||
|
|
||||||
|
@ -21,31 +19,14 @@ import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
|
||||||
@Mixin(PlayerEntityRenderer.class)
|
@Mixin(PlayerEntityRenderer.class)
|
||||||
abstract class MixinPlayerEntityRenderer
|
abstract class MixinPlayerEntityRenderer extends LivingEntityRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> {
|
||||||
extends LivingEntityRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>>
|
|
||||||
implements FeatureRoot<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> {
|
|
||||||
@Nullable
|
|
||||||
private AccessoryFeatureRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> accessories;
|
|
||||||
|
|
||||||
MixinPlayerEntityRenderer() { super(null, null, 0); }
|
MixinPlayerEntityRenderer() { super(null, null, 0); }
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public AccessoryFeatureRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> getAccessories() {
|
|
||||||
if (accessories == null) {
|
|
||||||
accessories = features.stream()
|
|
||||||
.filter(a -> a instanceof FeatureRoot)
|
|
||||||
.map(a -> ((FeatureRoot<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>>)a).getAccessories())
|
|
||||||
.findFirst()
|
|
||||||
.orElseGet(() -> new AccessoryFeatureRenderer<>(this));
|
|
||||||
}
|
|
||||||
return accessories;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "renderArm", at = @At("RETURN"))
|
@Inject(method = "renderArm", at = @At("RETURN"))
|
||||||
private void onRenderArm(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, AbstractClientPlayerEntity player, ModelPart arm, ModelPart sleeve, CallbackInfo info) {
|
private void onRenderArm(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, AbstractClientPlayerEntity player, ModelPart arm, ModelPart sleeve, CallbackInfo info) {
|
||||||
Arm a = this.getModel().leftArm == arm ? Arm.LEFT : Arm.RIGHT;
|
Arm a = this.getModel().leftArm == arm ? Arm.LEFT : Arm.RIGHT;
|
||||||
getAccessories().renderArm(matrices, vertexConsumers, light, player, arm, a);
|
((FeatureRoot<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>>)this).getAccessories().renderArm(matrices, vertexConsumers, light, player, arm, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "renderArm",
|
@Inject(method = "renderArm",
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T extends Spell> Stream<T> read(@Nullable SpellPredicate<T> type, boolean synchronize, boolean sendUpdate) {
|
private <T extends Spell> Stream<T> read(@Nullable SpellPredicate<T> type, boolean synchronize, boolean sendUpdate) {
|
||||||
if (synchronize && spells.fromNbt(owner.asEntity().getDataTracker().get(param)) && sendUpdate) {
|
if (synchronize && spells.fromNbt(owner.asEntity().getDataTracker().get(param)) && sendUpdate) {
|
||||||
owner.asEntity().getDataTracker().set(param, spells.toNbt());
|
write();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import net.minecraft.world.World;
|
||||||
/**
|
/**
|
||||||
* A connection class for updating and persisting an attached particle effect.
|
* A connection class for updating and persisting an attached particle effect.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class ParticleHandle {
|
public class ParticleHandle {
|
||||||
private final Map<String, Attachment> loadedEffects = new WeakHashMap<>();
|
private final Map<String, Attachment> loadedEffects = new WeakHashMap<>();
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,12 @@ public interface UParticles {
|
||||||
|
|
||||||
ParticleType<MagicParticleEffect> UNICORN_MAGIC = register("unicorn_magic", FabricParticleTypes.complex(MagicParticleEffect.FACTORY));
|
ParticleType<MagicParticleEffect> UNICORN_MAGIC = register("unicorn_magic", FabricParticleTypes.complex(MagicParticleEffect.FACTORY));
|
||||||
DefaultParticleType CHANGELING_MAGIC = register("changeling_magic", FabricParticleTypes.simple());
|
DefaultParticleType CHANGELING_MAGIC = register("changeling_magic", FabricParticleTypes.simple());
|
||||||
|
DefaultParticleType BUBBLE = register("bubble", FabricParticleTypes.simple());
|
||||||
|
|
||||||
ParticleType<OrientedBillboardParticleEffect> RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
ParticleType<OrientedBillboardParticleEffect> RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
||||||
DefaultParticleType RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.simple());
|
DefaultParticleType RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.simple());
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
ParticleType<OrientedBillboardParticleEffect> MAGIC_RUNES = register("magic_runes", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
ParticleType<OrientedBillboardParticleEffect> MAGIC_RUNES = register("magic_runes", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
||||||
|
|
||||||
DefaultParticleType RAIN_DROPS = register("rain_drops", FabricParticleTypes.simple());
|
DefaultParticleType RAIN_DROPS = register("rain_drops", FabricParticleTypes.simple());
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.minelittlepony.unicopia.util.shape;
|
package com.minelittlepony.unicopia.util.shape;
|
||||||
|
|
||||||
|
import org.spongepowered.include.com.google.common.base.Objects;
|
||||||
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.random.Random;
|
import net.minecraft.util.math.random.Random;
|
||||||
|
@ -102,6 +104,19 @@ public class Sphere implements Shape {
|
||||||
return stretch.multiply(rad);
|
return stretch.multiply(rad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return other instanceof Sphere o
|
||||||
|
&& Objects.equal(stretch, o.stretch)
|
||||||
|
&& hollow == o.hollow
|
||||||
|
&& Double.compare(rad, o.rad) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(stretch, hollow, rad);
|
||||||
|
}
|
||||||
|
|
||||||
public static double computeEllipsoidArea(double rad, Vec3d stretch) {
|
public static double computeEllipsoidArea(double rad, Vec3d stretch) {
|
||||||
double p = 1.6075;
|
double p = 1.6075;
|
||||||
double result = Math.pow(rad * stretch.x, p) * Math.pow(rad * stretch.y, p);
|
double result = Math.pow(rad * stretch.x, p) * Math.pow(rad * stretch.y, p);
|
||||||
|
|
5
src/main/resources/assets/unicopia/particles/bubble.json
Normal file
5
src/main/resources/assets/unicopia/particles/bubble.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
"minecraft:bubble"
|
||||||
|
]
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
|
@ -2,13 +2,13 @@
|
||||||
"parent": "unicopia:unicopia/earth/born_on_a_rock_farm",
|
"parent": "unicopia:unicopia/earth/born_on_a_rock_farm",
|
||||||
"display": {
|
"display": {
|
||||||
"icon": {
|
"icon": {
|
||||||
"item": "unicopia:rock"
|
"item": "unicopia:iron_horse_shoe"
|
||||||
},
|
},
|
||||||
"title": {
|
"title": {
|
||||||
"translate": "advancements.unicopia.sticks_and_stones.title"
|
"translate": "advancements.unicopia.dead_ringer.title"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"translate": "advancements.unicopia.sticks_and_stones.description"
|
"translate": "advancements.unicopia.dead_ringer.description"
|
||||||
},
|
},
|
||||||
"frame": "task",
|
"frame": "task",
|
||||||
"show_toast": true,
|
"show_toast": true,
|
||||||
|
@ -16,13 +16,13 @@
|
||||||
"hidden": true
|
"hidden": true
|
||||||
},
|
},
|
||||||
"criteria": {
|
"criteria": {
|
||||||
"killed_entity_with_rock": {
|
"killed_entity_with_horseshoe": {
|
||||||
"trigger": "minecraft:player_killed_entity",
|
"trigger": "minecraft:player_killed_entity",
|
||||||
"conditions": {
|
"conditions": {
|
||||||
"killing_blow": {
|
"killing_blow": {
|
||||||
"tags": [
|
"tags": [
|
||||||
{
|
{
|
||||||
"id": "unicopia:from_rocks",
|
"id": "unicopia:from_horseshoes",
|
||||||
"expected": true
|
"expected": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -31,6 +31,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"requirements": [
|
"requirements": [
|
||||||
[ "killed_entity_with_rock" ]
|
[ "killed_entity_with_horseshoe" ]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
"parent": "unicopia:unicopia/earth/born_on_a_rock_farm",
|
"parent": "unicopia:unicopia/earth/born_on_a_rock_farm",
|
||||||
"display": {
|
"display": {
|
||||||
"icon": {
|
"icon": {
|
||||||
"item": "unicopia:horseshoe"
|
"item": "unicopia:rock"
|
||||||
},
|
},
|
||||||
"title": {
|
"title": {
|
||||||
"translate": "advancements.unicopia.dead_ringer.title"
|
"translate": "advancements.unicopia.sticks_and_stones.title"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"translate": "advancements.unicopia.dead_ringer.description"
|
"translate": "advancements.unicopia.sticks_and_stones.description"
|
||||||
},
|
},
|
||||||
"frame": "task",
|
"frame": "task",
|
||||||
"show_toast": true,
|
"show_toast": true,
|
||||||
|
@ -16,13 +16,13 @@
|
||||||
"hidden": true
|
"hidden": true
|
||||||
},
|
},
|
||||||
"criteria": {
|
"criteria": {
|
||||||
"killed_entity_with_horseshoe": {
|
"killed_entity_with_rock": {
|
||||||
"trigger": "minecraft:player_killed_entity",
|
"trigger": "minecraft:player_killed_entity",
|
||||||
"conditions": {
|
"conditions": {
|
||||||
"killing_blow": {
|
"killing_blow": {
|
||||||
"tags": [
|
"tags": [
|
||||||
{
|
{
|
||||||
"id": "unicopia:from_horseshoes",
|
"id": "unicopia:from_rocks",
|
||||||
"expected": true
|
"expected": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -31,6 +31,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"requirements": [
|
"requirements": [
|
||||||
[ "killed_entity_with_horseshoe" ]
|
[ "killed_entity_with_rock" ]
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in a new issue