mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-17 18:34:23 +01:00
Added fairies
This commit is contained in:
parent
6a84f5d8b6
commit
596e01cc24
8 changed files with 468 additions and 44 deletions
|
@ -20,6 +20,7 @@ import com.minelittlepony.unicopia.client.render.IcarusWingsFeatureRenderer;
|
|||
import com.minelittlepony.unicopia.client.render.WingsFeatureRenderer;
|
||||
import com.minelittlepony.unicopia.client.render.entity.ButterflyEntityRenderer;
|
||||
import com.minelittlepony.unicopia.client.render.entity.CastSpellEntityRenderer;
|
||||
import com.minelittlepony.unicopia.client.render.entity.FairyEntityRenderer;
|
||||
import com.minelittlepony.unicopia.client.render.entity.SpellbookEntityRenderer;
|
||||
import com.minelittlepony.unicopia.entity.UEntities;
|
||||
import com.minelittlepony.unicopia.item.ChameleonItem;
|
||||
|
@ -70,6 +71,7 @@ public interface URenderers {
|
|||
EntityRendererRegistry.register(UEntities.BUTTERFLY, ButterflyEntityRenderer::new);
|
||||
EntityRendererRegistry.register(UEntities.FLOATING_ARTEFACT, FloatingArtefactEntityRenderer::new);
|
||||
EntityRendererRegistry.register(UEntities.CAST_SPELL, CastSpellEntityRenderer::new);
|
||||
EntityRendererRegistry.register(UEntities.FAIRY, FairyEntityRenderer::new);
|
||||
EntityRendererRegistry.register(UEntities.SPELLBOOK, SpellbookEntityRenderer::new);
|
||||
|
||||
ColorProviderRegistry.ITEM.register((stack, i) -> i > 0 ? -1 : ((DyeableItem)stack.getItem()).getColor(stack), UItems.FRIENDSHIP_BRACELET);
|
||||
|
|
|
@ -154,10 +154,7 @@ public class SphereParticle extends Particle implements Attachment {
|
|||
|
||||
protected void renderModel(MatrixStack matrices, VertexConsumer buffer, float lerpedRad, float tickDelta, int light) {
|
||||
float thickness = 0.05F;
|
||||
|
||||
matrices.push();
|
||||
SphereModel.SPHERE.render(matrices, buffer, light, 1, lerpedRad + thickness, 1, 1, 1, 0.8F);
|
||||
matrices.pop();
|
||||
SphereModel.SPHERE.render(matrices, buffer, light, 1, lerpedRad - thickness, 1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.client.render;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.client.render.VertexFormat.DrawMode;
|
||||
|
@ -19,7 +21,27 @@ public final class RenderLayers extends RenderLayer {
|
|||
.target(TRANSLUCENT_TARGET)
|
||||
.build(false));
|
||||
|
||||
private static final RenderLayer FAIRY = RenderLayer.of("fairy", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL,
|
||||
VertexFormat.DrawMode.QUADS, 256, true, true, RenderLayer.MultiPhaseParameters.builder()
|
||||
.shader(COLOR_SHADER)
|
||||
.transparency(TRANSLUCENT_TRANSPARENCY)
|
||||
.target(TRANSLUCENT_TARGET)
|
||||
.texturing(solid(120, 120, 0, 0.6F))
|
||||
.build(false));
|
||||
|
||||
public static RenderLayer getMagicGlow() {
|
||||
return MAGIC_GLOW;
|
||||
}
|
||||
|
||||
public static RenderLayer getFairy() {
|
||||
return FAIRY;
|
||||
}
|
||||
|
||||
public static Texturing solid(float r, float g, float b, float a) {
|
||||
return new Texturing("solid", () -> {
|
||||
RenderSystem.setShaderColor(r, g, b, a);
|
||||
}, () -> {
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package com.minelittlepony.unicopia.client.render.entity;
|
||||
|
||||
import com.minelittlepony.unicopia.client.particle.SphereModel;
|
||||
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||
import com.minelittlepony.unicopia.entity.FairyEntity;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory;
|
||||
import net.minecraft.client.render.entity.MobEntityRenderer;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class FairyEntityRenderer extends MobEntityRenderer<FairyEntity, FairyEntityRenderer.Model> {
|
||||
public FairyEntityRenderer(EntityRendererFactory.Context context) {
|
||||
super(context, new Model(), 0.25F);
|
||||
shadowOpacity = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getTexture(FairyEntity entity) {
|
||||
return PlayerScreenHandler.BLOCK_ATLAS_TEXTURE;
|
||||
}
|
||||
|
||||
public static class Model extends EntityModel<FairyEntity> {
|
||||
private float radius;
|
||||
|
||||
public Model() {
|
||||
super(texture -> RenderLayers.getFairy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
float thickness = 0.05F;
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(0, 1.5, 0);
|
||||
|
||||
SphereModel.SPHERE.render(matrices, vertexConsumer, light, overlay, radius - thickness, red, green, blue, 0.5F);
|
||||
SphereModel.SPHERE.render(matrices, vertexConsumer, light, overlay, radius, red, green, blue, 0.3F);
|
||||
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngles(FairyEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float headYaw, float headPitch) {
|
||||
radius = 0.125F + (float)Math.sin(entity.age * 0.1F) / 100F;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import java.util.Optional;
|
|||
import java.util.UUID;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.Levelled;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellContainer;
|
||||
|
@ -24,21 +23,16 @@ import net.minecraft.nbt.NbtCompound;
|
|||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
||||
|
||||
public class CastSpellEntity extends Entity implements Caster<LivingEntity>, LightEmittingEntity {
|
||||
private static final TrackedData<Float> GRAVITY = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||
|
||||
private static final TrackedData<Optional<UUID>> SPELL = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.OPTIONAL_UUID);
|
||||
|
||||
private static final LevelStore LEVELS = Levelled.fixed(0);
|
||||
|
||||
private final EntityPhysics<CastSpellEntity> physics = new EntityPhysics<>(this, GRAVITY);
|
||||
|
||||
private final EntityReference<LivingEntity> owner = new EntityReference<>();
|
||||
|
||||
private final SpellContainer spell = new SpellContainer.Delegate() {
|
||||
@Override
|
||||
public SpellContainer delegate() {
|
||||
|
@ -52,7 +46,8 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
}
|
||||
};
|
||||
|
||||
private BlockPos lastPos;
|
||||
private final EntityReference<LivingEntity> owner = new EntityReference<>();
|
||||
private final LightEmitter<?> emitter = new LightEmitter<>(this);
|
||||
|
||||
private int orphanedTicks;
|
||||
|
||||
|
@ -65,6 +60,11 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
getDataTracker().startTracking(SPELL, Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightLevel() {
|
||||
return 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getName() {
|
||||
Entity master = getMaster();
|
||||
|
@ -74,7 +74,6 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
return super.getName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
@ -83,23 +82,6 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (world.isClient) {
|
||||
BlockPos currentPos = getBlockPos();
|
||||
|
||||
if (world.isChunkLoaded(currentPos)) {
|
||||
try {
|
||||
world.getLightingProvider().addLightSource(currentPos, 11);
|
||||
|
||||
if (lastPos != null && !currentPos.equals(lastPos)) {
|
||||
world.getLightingProvider().checkBlock(lastPos);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Unicopia.LOGGER.error("Error updating lighting", e);
|
||||
}
|
||||
|
||||
lastPos = currentPos;
|
||||
}
|
||||
}
|
||||
LivingEntity master = getMaster();
|
||||
|
||||
if (master == null || master.isRemoved()) {
|
||||
|
@ -112,6 +94,8 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
|
||||
orphanedTicks = 0;
|
||||
|
||||
emitter.tick();
|
||||
|
||||
if (!dataTracker.get(SPELL).filter(spellId -> {
|
||||
return getSpellSlot().forEach(spell -> {
|
||||
return spell.getUuid().equals(spellId) ? Operation.ofBoolean(spell.tick(this, Situation.GROUND_ENTITY)) : Operation.SKIP;
|
||||
|
@ -121,27 +105,19 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(RemovalReason reason) {
|
||||
super.remove(reason);
|
||||
if (world.isClient) {
|
||||
world.getLightingProvider().checkBlock(getBlockPos());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaster(LivingEntity owner) {
|
||||
this.owner.set(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getEntity() {
|
||||
return this;
|
||||
public LivingEntity getMaster() {
|
||||
return owner.get(((Entity)this).world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LivingEntity getMaster() {
|
||||
return owner.get(world);
|
||||
public Entity getEntity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -182,15 +158,14 @@ public class CastSpellEntity extends Entity implements Caster<LivingEntity> {
|
|||
if (tag.contains("owner")) {
|
||||
owner.fromNBT(tag.getCompound("owner"));
|
||||
}
|
||||
orphanedTicks = 60;
|
||||
if (tag.contains("spellId")) {
|
||||
dataTracker.set(SPELL, Optional.ofNullable(tag.getUuid("spellId")));
|
||||
}
|
||||
orphanedTicks = 60;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<?> createSpawnPacket() {
|
||||
return Channel.SERVER_SPAWN_PROJECTILE.toPacket(new MsgSpawnProjectile(this));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
package com.minelittlepony.unicopia.entity;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Owned;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.entity.ai.FuzzyPositions;
|
||||
import net.minecraft.entity.ai.goal.Goal;
|
||||
import net.minecraft.entity.ai.goal.WanderAroundGoal;
|
||||
import net.minecraft.entity.ai.pathing.BirdNavigation;
|
||||
import net.minecraft.entity.ai.pathing.EntityNavigation;
|
||||
import net.minecraft.entity.ai.pathing.PathNodeType;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.mob.PathAwareEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class FairyEntity extends PathAwareEntity implements LightEmittingEntity, Owned<LivingEntity> {
|
||||
private final EntityReference<LivingEntity> owner = new EntityReference<>();
|
||||
|
||||
private final EntityReference<LivingEntity> assignment = new EntityReference<>();
|
||||
|
||||
private final LightEmitter<?> emitter = new LightEmitter<>(this);
|
||||
|
||||
private Optional<BlockPos> stayingPos = Optional.empty();
|
||||
|
||||
protected FairyEntity(EntityType<FairyEntity> type, World world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EntityNavigation createNavigation(World world) {
|
||||
BirdNavigation birdNavigation = new BirdNavigation(this, world);
|
||||
birdNavigation.setCanPathThroughDoors(true);
|
||||
birdNavigation.setCanSwim(true);
|
||||
birdNavigation.setCanEnterOpenDoors(true);
|
||||
return birdNavigation;
|
||||
}
|
||||
|
||||
public static DefaultAttributeContainer.Builder createMobAttributes() {
|
||||
return MobEntity.createMobAttributes()
|
||||
.add(EntityAttributes.GENERIC_MAX_HEALTH, 3)
|
||||
.add(EntityAttributes.GENERIC_FOLLOW_RANGE, 100)
|
||||
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initDataTracker() {
|
||||
super.initDataTracker();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initGoals() {
|
||||
goalSelector.add(5, new StayGoal());
|
||||
goalSelector.add(6, new FollowEntityGoal(2, 2, 30));
|
||||
goalSelector.add(7, new WanderAroundGoal(this, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightLevel() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaster(LivingEntity owner) {
|
||||
this.owner.set(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LivingEntity getMaster() {
|
||||
return owner.get(((Entity)this).world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fall(double heightDifference, boolean onGround, BlockState landedState, BlockPos landedPosition) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClimbing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStaying() {
|
||||
return stayingPos.isPresent();
|
||||
}
|
||||
|
||||
public void setStaying(BlockPos pos) {
|
||||
stayingPos = Optional.ofNullable(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
this.onGround = true;
|
||||
super.tick();
|
||||
emitter.tick();
|
||||
|
||||
if (world.random.nextInt(20) == 3) {
|
||||
world.addParticle(new MagicParticleEffect(0xFFFFFF), getParticleX(1), getY(), getParticleZ(1), 0, 0, 0);
|
||||
}
|
||||
|
||||
if (age % 60 == 0) {
|
||||
playSound(USounds.ITEM_MAGIC_AURA, 0.1F, 6);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void travel(Vec3d movementInput) {
|
||||
if (isTouchingWater()) {
|
||||
updateVelocity(0.02f, movementInput);
|
||||
move(MovementType.SELF, getVelocity());
|
||||
setVelocity(getVelocity().multiply(0.8f));
|
||||
} else if (isInLava()) {
|
||||
updateVelocity(0.02f, movementInput);
|
||||
move(MovementType.SELF, getVelocity());
|
||||
setVelocity(getVelocity().multiply(0.5));
|
||||
} else {
|
||||
float f = 0.91f;
|
||||
if (onGround) {
|
||||
f = world.getBlockState(getBlockPos().down()).getBlock().getSlipperiness() * 0.91f;
|
||||
}
|
||||
float g = 0.16277137f / (f * f * f);
|
||||
f = 0.91f;
|
||||
if (onGround) {
|
||||
f = world.getBlockState(getBlockPos().down()).getBlock().getSlipperiness() * 0.91f;
|
||||
}
|
||||
updateVelocity(onGround ? 0.1f * g : 0.02f, movementInput);
|
||||
move(MovementType.SELF, getVelocity());
|
||||
setVelocity(getVelocity().multiply(f));
|
||||
}
|
||||
updateLimbs(this, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActionResult interactMob(PlayerEntity player, Hand hand) {
|
||||
|
||||
if (hand == Hand.MAIN_HAND && isStaying() && player == getMaster()) {
|
||||
stayingPos = Optional.empty();
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved() {
|
||||
super.onRemoved();
|
||||
emitter.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeCustomDataToNbt(NbtCompound tag) {
|
||||
super.writeCustomDataToNbt(tag);
|
||||
tag.put("owner", owner.toNBT());
|
||||
stayingPos.ifPresent(pos -> {
|
||||
tag.put("stayingPos", NbtHelper.fromBlockPos(pos));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readCustomDataFromNbt(NbtCompound tag) {
|
||||
super.readCustomDataFromNbt(tag);
|
||||
if (tag.contains("owner")) {
|
||||
owner.fromNBT(tag.getCompound("owner"));
|
||||
}
|
||||
stayingPos = tag.contains("stayingPos") ? Optional.of(NbtHelper.toBlockPos(tag.getCompound("stayingPos"))) : Optional.empty();
|
||||
}
|
||||
|
||||
class FollowEntityGoal extends Goal {
|
||||
@Nullable
|
||||
private LivingEntity target;
|
||||
|
||||
private final double speed;
|
||||
private int updateCountdownTicks;
|
||||
|
||||
private final float minDistance;
|
||||
private final float maxDistance;
|
||||
private float oldWaterPathFindingPenalty;
|
||||
|
||||
public FollowEntityGoal(double speed, float minDistance, float maxDistance) {
|
||||
this.speed = speed;
|
||||
this.minDistance = minDistance;
|
||||
this.maxDistance = maxDistance;
|
||||
setControls(EnumSet.of(Goal.Control.MOVE, Goal.Control.LOOK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStart() {
|
||||
target = assignment.get(world);
|
||||
|
||||
if (target == null) {
|
||||
target = getMaster();
|
||||
}
|
||||
if (target == null) {
|
||||
target = world.getClosestPlayer(FairyEntity.this, maxDistance);
|
||||
}
|
||||
return target != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldContinue() {
|
||||
return target != null && !isStaying() && !getNavigation().isIdle() && squaredDistanceTo(target) > minDistance * minDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
updateCountdownTicks = 0;
|
||||
oldWaterPathFindingPenalty = getPathfindingPenalty(PathNodeType.WATER);
|
||||
setPathfindingPenalty(PathNodeType.WATER, 0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
target = null;
|
||||
getNavigation().stop();
|
||||
setPathfindingPenalty(PathNodeType.WATER, oldWaterPathFindingPenalty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (target == null || isLeashed() || isStaying()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getLookControl().lookAt(target, 10, getMaxLookPitchChange());
|
||||
|
||||
if (--updateCountdownTicks > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateCountdownTicks = getTickCount(10);
|
||||
|
||||
if (getPos().squaredDistanceTo(target.getPos()) <= minDistance * minDistance) {
|
||||
|
||||
BlockPos pos = FuzzyPositions.localFuzz(FairyEntity.this.world.random, 5, 5);
|
||||
if (pos != null) {
|
||||
getNavigation().startMovingTo(pos.getX(), pos.getY(), pos.getZ(), speed);
|
||||
} else {
|
||||
getNavigation().stop();
|
||||
}
|
||||
} else {
|
||||
getNavigation().startMovingTo(target, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class StayGoal extends Goal {
|
||||
private int updateCountdownTicks;
|
||||
|
||||
public StayGoal() {
|
||||
setControls(EnumSet.of(Goal.Control.MOVE, Goal.Control.LOOK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStart() {
|
||||
return isStaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldContinue() {
|
||||
return isStaying() && !getNavigation().isIdle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
updateCountdownTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
getNavigation().stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (--updateCountdownTicks > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateCountdownTicks = getTickCount(10);
|
||||
|
||||
stayingPos.ifPresent(pos -> {
|
||||
if (pos.getSquaredDistance(getBlockPos()) <= 1) {
|
||||
getNavigation().stop();
|
||||
} else {
|
||||
getNavigation().startMovingTo(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, speed);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.minelittlepony.unicopia.entity;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public interface LightEmittingEntity {
|
||||
|
||||
int getLightLevel();
|
||||
|
||||
static class LightEmitter<T extends Entity & LightEmittingEntity> {
|
||||
private BlockPos lastPos;
|
||||
|
||||
private final T entity;
|
||||
|
||||
public LightEmitter(T entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void tick() {
|
||||
|
||||
if (entity.isRemoved()) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity.world.isClient) {
|
||||
int light = entity.getLightLevel();
|
||||
|
||||
if (light <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos currentPos = entity.getBlockPos();
|
||||
|
||||
if (entity.world.isChunkLoaded(currentPos)) {
|
||||
try {
|
||||
if (lastPos != null && !currentPos.equals(lastPos)) {
|
||||
entity.world.getLightingProvider().checkBlock(lastPos);
|
||||
}
|
||||
|
||||
entity.world.getLightingProvider().addLightSource(currentPos, light);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
lastPos = currentPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remove() {
|
||||
if (entity.world.isClient) {
|
||||
try {
|
||||
entity.world.getLightingProvider().checkBlock(entity.getBlockPos());
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,10 @@ public interface UEntities {
|
|||
.dimensions(EntityDimensions.fixed(1, 1)));
|
||||
EntityType<CastSpellEntity> CAST_SPELL = register("cast_spell", FabricEntityTypeBuilder.create(SpawnGroup.MISC, CastSpellEntity::new)
|
||||
.trackRangeBlocks(200)
|
||||
.dimensions(EntityDimensions.fixed(1, 1)));
|
||||
.dimensions(EntityDimensions.fixed(1, 0.4F)));
|
||||
EntityType<FairyEntity> FAIRY = register("fairy", FabricEntityTypeBuilder.create(SpawnGroup.MISC, FairyEntity::new)
|
||||
.trackRangeBlocks(200)
|
||||
.dimensions(EntityDimensions.fixed(0.1F, 0.1F)));
|
||||
EntityType<SpellbookEntity> SPELLBOOK = register("spellbook", FabricEntityTypeBuilder.create(SpawnGroup.MISC, SpellbookEntity::new)
|
||||
.trackRangeBlocks(200)
|
||||
.dimensions(EntityDimensions.fixed(0.9F, 0.25F)));
|
||||
|
@ -43,6 +46,7 @@ public interface UEntities {
|
|||
static void bootstrap() {
|
||||
FabricDefaultAttributeRegistry.register(BUTTERFLY, ButterflyEntity.createButterflyAttributes());
|
||||
FabricDefaultAttributeRegistry.register(SPELLBOOK, SpellbookEntity.createMobAttributes());
|
||||
FabricDefaultAttributeRegistry.register(FAIRY, FairyEntity.createMobAttributes());
|
||||
|
||||
final Predicate<BiomeSelectionContext> butterflySpawnable = BiomeSelectors.foundInOverworld()
|
||||
.and(ctx -> ctx.getBiome().getPrecipitation() == Biome.Precipitation.RAIN);
|
||||
|
|
Loading…
Reference in a new issue