mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 19:46:42 +01:00
Added respawn logic to place seaponies in water
This commit is contained in:
parent
c656eb2309
commit
873297ca44
2 changed files with 66 additions and 28 deletions
|
@ -54,6 +54,7 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.registry.tag.DamageTypeTags;
|
||||
import net.minecraft.registry.tag.FluidTags;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.Text;
|
||||
|
@ -340,11 +341,12 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
|||
}
|
||||
|
||||
public void onSpawn() {
|
||||
if (entity.getWorld() instanceof ServerWorld sw
|
||||
&& getObservedSpecies() == Race.BAT
|
||||
&& sw.getServer().getSaveProperties().getGameMode() != GameMode.ADVENTURE
|
||||
&& MeteorlogicalUtil.isPositionExposedToSun(sw, getOrigin())) {
|
||||
SpawnLocator.selectSpawnPosition(sw, entity);
|
||||
if (entity.getWorld() instanceof ServerWorld sw && sw.getServer().getSaveProperties().getGameMode() != GameMode.ADVENTURE) {
|
||||
boolean mustAvoidSun = getObservedSpecies() == Race.BAT && MeteorlogicalUtil.isPositionExposedToSun(sw, getOrigin());
|
||||
boolean mustAvoidAir = getCompositeRace().includes(Race.SEAPONY) && !sw.getFluidState(getOrigin()).isIn(FluidTags.WATER);
|
||||
if (mustAvoidSun || mustAvoidAir) {
|
||||
SpawnLocator.selectSpawnPosition(sw, entity, mustAvoidAir, mustAvoidSun);
|
||||
}
|
||||
}
|
||||
ticksSunImmunity = INITIAL_SUN_IMMUNITY;
|
||||
}
|
||||
|
|
|
@ -1,37 +1,68 @@
|
|||
package com.minelittlepony.unicopia.entity.player;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.util.MeteorlogicalUtil;
|
||||
|
||||
import net.minecraft.entity.ai.FuzzyPositions;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.registry.tag.FluidTags;
|
||||
import net.minecraft.server.network.SpawnLocating;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
|
||||
public class SpawnLocator extends SpawnLocating {
|
||||
|
||||
public static BlockPos findSafeSpawnLocation(ServerWorld world, int x, int z) {
|
||||
return SpawnLocating.findOverworldSpawn(world, x, z);
|
||||
}
|
||||
|
||||
public static Optional<BlockPos> fuzz(ServerWorld world, BlockPos pos, int horizontal, int vertical) {
|
||||
|
||||
for (int attempt = 0; attempt < 6; attempt++) {
|
||||
BlockPos target = FuzzyPositions.localFuzz(world.random, horizontal, vertical);
|
||||
target = findSafeSpawnLocation(world, target.getX(), target.getZ());
|
||||
|
||||
if (target != null) {
|
||||
return Optional.of(target);
|
||||
}
|
||||
private static BlockPos findSafeSpawnLocation(ServerWorld world, int x, int z, boolean avoidAir) {
|
||||
if (!avoidAir) {
|
||||
return findOverworldSpawn(world, x, z);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
boolean hasCeiling = world.getDimension().hasCeiling();
|
||||
WorldChunk chunk = world.getChunk(ChunkSectionPos.getSectionCoord(x), ChunkSectionPos.getSectionCoord(z));
|
||||
int startHeight = hasCeiling
|
||||
? world.getChunkManager().getChunkGenerator().getSpawnHeight(world)
|
||||
: chunk.sampleHeightmap(Heightmap.Type.MOTION_BLOCKING, x & 0xF, z & 0xF);
|
||||
if (startHeight < world.getBottomY()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int terrainHeight = chunk.sampleHeightmap(Heightmap.Type.WORLD_SURFACE, x & 0xF, z & 0xF);
|
||||
if (terrainHeight <= startHeight && terrainHeight > chunk.sampleHeightmap(Heightmap.Type.OCEAN_FLOOR, x & 0xF, z & 0xF)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
||||
for (int y = startHeight + 1; y >= world.getBottomY(); --y) {
|
||||
mutable.set(x, y, z);
|
||||
BlockState state = world.getBlockState(mutable);
|
||||
FluidState fluid = state.getFluidState();
|
||||
if (fluid.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!fluid.isIn(FluidTags.WATER)) {
|
||||
break;
|
||||
}
|
||||
if (!Block.isFaceFullSquare(state.getCollisionShape(world, mutable), Direction.UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return mutable.up().toImmutable();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void selectSpawnPosition(ServerWorld world, PlayerEntity entity) {
|
||||
private static boolean checkAtmosphere(ServerWorld world, BlockPos pos, boolean avoidAir) {
|
||||
if (avoidAir) {
|
||||
return world.getFluidState(pos).isIn(FluidTags.WATER);
|
||||
|
||||
}
|
||||
return world.getFluidState(pos).isEmpty();
|
||||
}
|
||||
|
||||
public static void selectSpawnPosition(ServerWorld world, PlayerEntity entity, boolean avoidAir, boolean avoidSun) {
|
||||
BlockPos spawnPos = world.getSpawnPos();
|
||||
int spawnRadius = Math.min(
|
||||
MathHelper.floor(world.getWorldBorder().getDistanceInsideBorder(spawnPos.getX(), spawnPos.getZ())),
|
||||
|
@ -53,7 +84,8 @@ public class SpawnLocator extends SpawnLocating {
|
|||
|
||||
BlockPos candidatePos = findSafeSpawnLocation(world,
|
||||
spawnPos.getX() + x - spawnRadius,
|
||||
spawnPos.getZ() + z - spawnRadius
|
||||
spawnPos.getZ() + z - spawnRadius,
|
||||
avoidAir
|
||||
);
|
||||
|
||||
if (candidatePos == null) {
|
||||
|
@ -70,7 +102,7 @@ public class SpawnLocator extends SpawnLocating {
|
|||
mutable.move(0, -1, 0);
|
||||
}
|
||||
|
||||
if (!world.getFluidState(mutable).isEmpty()) {
|
||||
if (!checkAtmosphere(world, mutable, avoidAir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -78,13 +110,17 @@ public class SpawnLocator extends SpawnLocating {
|
|||
mutable.move(0, 1, 0);
|
||||
}
|
||||
|
||||
if (!world.getFluidState(mutable).isEmpty()) {
|
||||
if (!checkAtmosphere(world, mutable, avoidAir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entity.refreshPositionAndAngles(mutable, 0, 0);
|
||||
|
||||
if (!world.isSpaceEmpty(entity) || MeteorlogicalUtil.isPositionExposedToSun(world, mutable)) {
|
||||
if (!world.isSpaceEmpty(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (avoidSun && MeteorlogicalUtil.isPositionExposedToSun(world, mutable)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue