mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Spawn batponies in appropriate locations to avoid burning their eyes
This commit is contained in:
parent
d720a37cd9
commit
ab97a7b6ef
5 changed files with 114 additions and 14 deletions
|
@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.UTags;
|
import com.minelittlepony.unicopia.UTags;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
@ -14,7 +15,9 @@ import net.minecraft.entity.effect.StatusEffect;
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
import net.minecraft.entity.effect.StatusEffectCategory;
|
import net.minecraft.entity.effect.StatusEffectCategory;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.LightType;
|
import net.minecraft.world.LightType;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class SunBlindnessStatusEffect extends StatusEffect {
|
public class SunBlindnessStatusEffect extends StatusEffect {
|
||||||
public static final int MAX_DURATION = 250;
|
public static final int MAX_DURATION = 250;
|
||||||
|
@ -27,7 +30,7 @@ public class SunBlindnessStatusEffect extends StatusEffect {
|
||||||
public void applyUpdateEffect(LivingEntity entity, int amplifier) {
|
public void applyUpdateEffect(LivingEntity entity, int amplifier) {
|
||||||
StatusEffectInstance state = entity.getStatusEffect(this);
|
StatusEffectInstance state = entity.getStatusEffect(this);
|
||||||
|
|
||||||
if (state == null) {
|
if (state == null || isSunImmune(entity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,9 +53,15 @@ public class SunBlindnessStatusEffect extends StatusEffect {
|
||||||
return duration > 0;
|
return duration > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isSunImmune(LivingEntity entity) {
|
||||||
|
return entity.hasStatusEffect(StatusEffects.BLINDNESS)
|
||||||
|
|| entity.hasPortalCooldown()
|
||||||
|
|| Pony.of(entity).map(pony -> pony.isSunImmune()).orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean hasSunExposure(LivingEntity entity) {
|
public static boolean hasSunExposure(LivingEntity entity) {
|
||||||
|
|
||||||
if (entity.hasPortalCooldown()) {
|
if (isSunImmune(entity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,21 +73,21 @@ public class SunBlindnessStatusEffect extends StatusEffect {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.SHADES)
|
||||||
if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.SHADES)) {
|
|| TrinketsDelegate.getInstance().getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.SHADES))
|
||||||
|
|| entity.isSubmergedInWater()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TrinketsDelegate.getInstance().getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.SHADES))) {
|
return isPositionExposedToSun(entity.world, entity.getBlockPos());
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPositionExposedToSun(World world, BlockPos pos) {
|
||||||
|
if (world.isClient) {
|
||||||
|
world.calculateAmbientDarkness();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.world.isClient) {
|
return world.getDimension().hasSkyLight() && world.getLightLevel(LightType.SKY, pos) >= 12 && !world.isRaining() && !world.isThundering() && world.isDay();
|
||||||
entity.world.calculateAmbientDarkness();
|
|
||||||
}
|
|
||||||
|
|
||||||
int light = entity.world.getLightLevel(LightType.SKY, entity.getBlockPos());
|
|
||||||
|
|
||||||
return !(entity.isSubmergedInWater() || light < 12 || entity.world.isRaining() || entity.world.isThundering() || !entity.world.isDay());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
|
import net.minecraft.world.GameMode;
|
||||||
|
|
||||||
public class Pony extends Living<PlayerEntity> implements Transmittable, Copieable<Pony>, UpdateCallback {
|
public class Pony extends Living<PlayerEntity> implements Transmittable, Copieable<Pony>, UpdateCallback {
|
||||||
|
|
||||||
|
@ -107,6 +108,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
|
|
||||||
private int ticksInSun;
|
private int ticksInSun;
|
||||||
private boolean hasShades;
|
private boolean hasShades;
|
||||||
|
private int ticksSunImmunity = 20;
|
||||||
|
|
||||||
private Animation animation = Animation.NONE;
|
private Animation animation = Animation.NONE;
|
||||||
private int animationMaxDuration;
|
private int animationMaxDuration;
|
||||||
|
@ -221,6 +223,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
this.invisible = invisible;
|
this.invisible = invisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSunImmune() {
|
||||||
|
return ticksSunImmunity > 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Affinity getAffinity() {
|
public Affinity getAffinity() {
|
||||||
return getSpecies().getAffinity();
|
return getSpecies().getAffinity();
|
||||||
|
@ -270,6 +276,15 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
return interpolator;
|
return interpolator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSpawn() {
|
||||||
|
if (entity.world instanceof ServerWorld sw
|
||||||
|
&& getSpecies() == Race.BAT
|
||||||
|
&& sw.getServer().getSaveProperties().getGameMode() != GameMode.ADVENTURE
|
||||||
|
&& SunBlindnessStatusEffect.isPositionExposedToSun(sw, getOrigin())) {
|
||||||
|
SpawnLocator.selectSpawnPosition(sw, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean beforeUpdate() {
|
public boolean beforeUpdate() {
|
||||||
|
|
||||||
|
@ -355,6 +370,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (ticksSunImmunity > 0) {
|
||||||
|
ticksSunImmunity--;
|
||||||
|
}
|
||||||
|
|
||||||
if (animationDuration >= 0 && --animationDuration <= 0) {
|
if (animationDuration >= 0 && --animationDuration <= 0) {
|
||||||
setAnimation(Animation.NONE);
|
setAnimation(Animation.NONE);
|
||||||
}
|
}
|
||||||
|
@ -618,6 +637,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
mana.getXp().set(oldPlayer.getMagicalReserves().getXp().get());
|
mana.getXp().set(oldPlayer.getMagicalReserves().getXp().get());
|
||||||
advancementProgress.putAll(oldPlayer.getAdvancementProgress());
|
advancementProgress.putAll(oldPlayer.getAdvancementProgress());
|
||||||
setDirty();
|
setDirty();
|
||||||
|
onSpawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.minelittlepony.unicopia.entity.player;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.server.network.SpawnLocating;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.math.*;
|
||||||
|
import net.minecraft.util.math.random.Random;
|
||||||
|
|
||||||
|
public class SpawnLocator extends SpawnLocating {
|
||||||
|
|
||||||
|
public static void selectSpawnPosition(ServerWorld world, PlayerEntity entity) {
|
||||||
|
BlockPos spawnPos = world.getSpawnPos();
|
||||||
|
int spawnRadius = Math.min(
|
||||||
|
MathHelper.floor(world.getWorldBorder().getDistanceInsideBorder(spawnPos.getX(), spawnPos.getZ())),
|
||||||
|
Math.max(0, world.getServer().getSpawnRadius(world))
|
||||||
|
);
|
||||||
|
|
||||||
|
long l = spawnRadius * 2 + 1;
|
||||||
|
long m = l * l;
|
||||||
|
int spawnArea = m > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)m;
|
||||||
|
int offsetMultiplier = spawnArea <= 16 ? spawnArea - 1 : 17;
|
||||||
|
int rng = Random.create().nextInt(spawnArea);
|
||||||
|
|
||||||
|
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
||||||
|
|
||||||
|
for (int attempt = 0; attempt < spawnArea; attempt++) {
|
||||||
|
int tile = (rng + offsetMultiplier * attempt) % spawnArea;
|
||||||
|
int x = tile % (spawnRadius * 2 + 1);
|
||||||
|
int z = tile / (spawnRadius * 2 + 1);
|
||||||
|
|
||||||
|
BlockPos candidatePos = findOverworldSpawn(world,
|
||||||
|
spawnPos.getX() + x - spawnRadius,
|
||||||
|
spawnPos.getZ() + z - spawnRadius
|
||||||
|
);
|
||||||
|
|
||||||
|
if (candidatePos == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable.set(candidatePos);
|
||||||
|
mutable.move(0, -1, 0);
|
||||||
|
|
||||||
|
while (!world.isAir(mutable) && mutable.getY() >= spawnPos.getY() - spawnRadius * 2 && !world.isOutOfHeightLimit(mutable)) {
|
||||||
|
mutable.move(0, -1, 0);
|
||||||
|
}
|
||||||
|
while (world.isAir(mutable) && mutable.getY() >= spawnPos.getY() - spawnRadius * 2 && !world.isOutOfHeightLimit(mutable)) {
|
||||||
|
mutable.move(0, -1, 0);
|
||||||
|
}
|
||||||
|
if (!world.isAir(mutable)) {
|
||||||
|
mutable.move(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.getFluidState(mutable).isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.refreshPositionAndAngles(mutable, 0, 0);
|
||||||
|
|
||||||
|
if (!world.isSpaceEmpty(entity) || SunBlindnessStatusEffect.isPositionExposedToSun(world, mutable)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import com.minelittlepony.unicopia.entity.PonyContainer;
|
import com.minelittlepony.unicopia.entity.PonyContainer;
|
||||||
import com.minelittlepony.unicopia.entity.duck.ServerPlayerEntityDuck;
|
import com.minelittlepony.unicopia.entity.duck.ServerPlayerEntityDuck;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.screen.ScreenHandlerListener;
|
import net.minecraft.screen.ScreenHandlerListener;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
|
@ -47,6 +47,10 @@ public class MsgRequestSpeciesChange implements Packet<ServerPlayerEntity> {
|
||||||
|
|
||||||
if (force || player.getActualSpecies().isDefault() || (player.getActualSpecies() == worldDefaultRace && !player.isSpeciesPersisted())) {
|
if (force || player.getActualSpecies().isDefault() || (player.getActualSpecies() == worldDefaultRace && !player.isSpeciesPersisted())) {
|
||||||
player.setSpecies(newRace.isPermitted(sender) ? newRace : worldDefaultRace);
|
player.setSpecies(newRace.isPermitted(sender) ? newRace : worldDefaultRace);
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
player.onSpawn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.SERVER_PLAYER_CAPABILITIES.send(sender, new MsgPlayerCapabilities(true, player));
|
Channel.SERVER_PLAYER_CAPABILITIES.send(sender, new MsgPlayerCapabilities(true, player));
|
||||||
|
|
Loading…
Reference in a new issue