package org.bukkit.craftbukkit; import com.google.common.base.Preconditions; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Random; import net.minecraft.core.BlockPosition; import net.minecraft.core.EnumDirection; import net.minecraft.core.IRegistry; import net.minecraft.data.worldgen.BiomeDecoratorGroups; import net.minecraft.world.entity.EntityAreaEffectCloud; import net.minecraft.world.entity.EntityExperienceOrb; import net.minecraft.world.entity.EntityInsentient; import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.EnumMobSpawn; import net.minecraft.world.entity.GroupDataEntity; import net.minecraft.world.entity.decoration.EntityArmorStand; import net.minecraft.world.entity.decoration.EntityHanging; import net.minecraft.world.entity.decoration.EntityItemFrame; import net.minecraft.world.entity.decoration.EntityLeash; import net.minecraft.world.entity.decoration.EntityPainting; import net.minecraft.world.entity.item.EntityFallingBlock; import net.minecraft.world.entity.item.EntityTNTPrimed; import net.minecraft.world.entity.monster.EntityZombie; import net.minecraft.world.entity.projectile.EntityEgg; import net.minecraft.world.entity.projectile.EntityEnderSignal; import net.minecraft.world.entity.projectile.EntityEvokerFangs; import net.minecraft.world.entity.projectile.EntityFireball; import net.minecraft.world.entity.projectile.EntityFireworks; import net.minecraft.world.entity.projectile.EntityPotion; import net.minecraft.world.entity.projectile.EntitySnowball; import net.minecraft.world.entity.projectile.EntityTippedArrow; import net.minecraft.world.entity.vehicle.EntityBoat; import net.minecraft.world.entity.vehicle.EntityMinecartChest; import net.minecraft.world.entity.vehicle.EntityMinecartCommandBlock; import net.minecraft.world.entity.vehicle.EntityMinecartFurnace; import net.minecraft.world.entity.vehicle.EntityMinecartHopper; import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; import net.minecraft.world.entity.vehicle.EntityMinecartRideable; import net.minecraft.world.entity.vehicle.EntityMinecartTNT; import net.minecraft.world.level.GeneratorAccessSeed; import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.block.BlockChorusFlower; import net.minecraft.world.level.block.BlockDiodeAbstract; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; import net.minecraft.world.phys.AxisAlignedBB; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.RegionAccessor; import org.bukkit.TreeType; import org.bukkit.block.Biome; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.potion.CraftPotionUtil; import org.bukkit.craftbukkit.util.BlockStateListPopulator; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.entity.AbstractArrow; import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.AbstractSkeleton; import org.bukkit.entity.AbstractVillager; import org.bukkit.entity.Ambient; import org.bukkit.entity.AreaEffectCloud; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Axolotl; import org.bukkit.entity.Bat; import org.bukkit.entity.Bee; import org.bukkit.entity.Blaze; import org.bukkit.entity.Boat; import org.bukkit.entity.Cat; import org.bukkit.entity.CaveSpider; import org.bukkit.entity.ChestedHorse; import org.bukkit.entity.Chicken; import org.bukkit.entity.Cod; import org.bukkit.entity.ComplexLivingEntity; import org.bukkit.entity.Cow; import org.bukkit.entity.Creeper; import org.bukkit.entity.Dolphin; import org.bukkit.entity.Donkey; import org.bukkit.entity.DragonFireball; import org.bukkit.entity.Drowned; import org.bukkit.entity.Egg; import org.bukkit.entity.ElderGuardian; import org.bukkit.entity.EnderCrystal; import org.bukkit.entity.EnderDragon; import org.bukkit.entity.EnderPearl; import org.bukkit.entity.EnderSignal; import org.bukkit.entity.Enderman; import org.bukkit.entity.Endermite; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Evoker; import org.bukkit.entity.EvokerFangs; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Fireball; import org.bukkit.entity.Firework; import org.bukkit.entity.Fish; import org.bukkit.entity.Fox; import org.bukkit.entity.Ghast; import org.bukkit.entity.Giant; import org.bukkit.entity.GlowItemFrame; import org.bukkit.entity.GlowSquid; import org.bukkit.entity.Goat; import org.bukkit.entity.Golem; import org.bukkit.entity.Guardian; import org.bukkit.entity.Hanging; import org.bukkit.entity.Hoglin; import org.bukkit.entity.Husk; import org.bukkit.entity.Illager; import org.bukkit.entity.Illusioner; import org.bukkit.entity.IronGolem; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.LeashHitch; import org.bukkit.entity.LightningStrike; import org.bukkit.entity.LingeringPotion; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Llama; import org.bukkit.entity.LlamaSpit; import org.bukkit.entity.MagmaCube; import org.bukkit.entity.Marker; import org.bukkit.entity.Minecart; import org.bukkit.entity.Mule; import org.bukkit.entity.MushroomCow; import org.bukkit.entity.Ocelot; import org.bukkit.entity.Painting; import org.bukkit.entity.Panda; import org.bukkit.entity.Parrot; import org.bukkit.entity.Phantom; import org.bukkit.entity.Pig; import org.bukkit.entity.PigZombie; import org.bukkit.entity.Piglin; import org.bukkit.entity.PiglinBrute; import org.bukkit.entity.Pillager; import org.bukkit.entity.Player; import org.bukkit.entity.PolarBear; import org.bukkit.entity.Projectile; import org.bukkit.entity.PufferFish; import org.bukkit.entity.Rabbit; import org.bukkit.entity.Ravager; import org.bukkit.entity.Salmon; import org.bukkit.entity.Sheep; import org.bukkit.entity.Shulker; import org.bukkit.entity.ShulkerBullet; import org.bukkit.entity.Silverfish; import org.bukkit.entity.Skeleton; import org.bukkit.entity.SkeletonHorse; import org.bukkit.entity.Slime; import org.bukkit.entity.SmallFireball; import org.bukkit.entity.Snowball; import org.bukkit.entity.Snowman; import org.bukkit.entity.SpectralArrow; import org.bukkit.entity.Spellcaster; import org.bukkit.entity.Spider; import org.bukkit.entity.Squid; import org.bukkit.entity.Stray; import org.bukkit.entity.Strider; import org.bukkit.entity.TNTPrimed; import org.bukkit.entity.Tameable; import org.bukkit.entity.ThrownExpBottle; import org.bukkit.entity.ThrownPotion; import org.bukkit.entity.TippedArrow; import org.bukkit.entity.TraderLlama; import org.bukkit.entity.Trident; import org.bukkit.entity.TropicalFish; import org.bukkit.entity.Turtle; import org.bukkit.entity.Vex; import org.bukkit.entity.Villager; import org.bukkit.entity.Vindicator; import org.bukkit.entity.WanderingTrader; import org.bukkit.entity.Witch; import org.bukkit.entity.Wither; import org.bukkit.entity.WitherSkeleton; import org.bukkit.entity.WitherSkull; import org.bukkit.entity.Wolf; import org.bukkit.entity.Zoglin; import org.bukkit.entity.Zombie; import org.bukkit.entity.ZombieHorse; import org.bukkit.entity.ZombieVillager; import org.bukkit.entity.minecart.CommandMinecart; import org.bukkit.entity.minecart.ExplosiveMinecart; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.entity.minecart.PoweredMinecart; import org.bukkit.entity.minecart.SpawnerMinecart; import org.bukkit.entity.minecart.StorageMinecart; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionType; import org.bukkit.util.Consumer; import org.bukkit.util.Vector; public abstract class CraftRegionAccessor implements RegionAccessor { public abstract GeneratorAccessSeed getHandle(); public boolean isNormalWorld() { return getHandle() instanceof net.minecraft.server.level.WorldServer; } @Override public Biome getBiome(Location location) { return getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } @Override public Biome getBiome(int x, int y, int z) { return CraftBlock.biomeBaseToBiome(getHandle().t().d(IRegistry.BIOME_REGISTRY), getHandle().getBiome(x >> 2, y >> 2, z >> 2)); } @Override public void setBiome(Location location, Biome biome) { setBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ(), biome); } @Override public void setBiome(int x, int y, int z, Biome biome) { Preconditions.checkArgument(biome != Biome.CUSTOM, "Cannot set the biome to %s", biome); BiomeBase biomeBase = CraftBlock.biomeToBiomeBase(getHandle().t().d(IRegistry.BIOME_REGISTRY), biome); setBiome(x, y, z, biomeBase); } public abstract void setBiome(int x, int y, int z, BiomeBase biomeBase); @Override public BlockState getBlockState(Location location) { return getBlockState(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } @Override public BlockState getBlockState(int x, int y, int z) { return CraftBlock.at(getHandle(), new BlockPosition(x, y, z)).getState(); } @Override public BlockData getBlockData(Location location) { return getBlockData(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } @Override public BlockData getBlockData(int x, int y, int z) { return CraftBlockData.fromData(getData(x, y, z)); } @Override public Material getType(Location location) { return getType(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } @Override public Material getType(int x, int y, int z) { return CraftMagicNumbers.getMaterial(getData(x, y, z).getBlock()); } private IBlockData getData(int x, int y, int z) { return getHandle().getType(new BlockPosition(x, y, z)); } @Override public void setBlockData(Location location, BlockData blockData) { setBlockData(location.getBlockX(), location.getBlockY(), location.getBlockZ(), blockData); } @Override public void setBlockData(int x, int y, int z, BlockData blockData) { CraftBlock.at(getHandle(), new BlockPosition(x, y, z)).setTypeAndData(((CraftBlockData) blockData).getState(), true); } @Override public void setType(Location location, Material material) { setType(location.getBlockX(), location.getBlockY(), location.getBlockZ(), material); } @Override public void setType(int x, int y, int z, Material material) { setBlockData(x, y, z, material.createBlockData()); } @Override public boolean generateTree(Location location, Random random, TreeType treeType) { BlockPosition pos = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); return generateTree(getHandle(), getHandle().getMinecraftWorld().getChunkProvider().generator, pos, random, treeType); } @Override public boolean generateTree(Location location, Random random, TreeType treeType, Consumer consumer) { BlockPosition pos = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); BlockStateListPopulator populator = new BlockStateListPopulator(getHandle()); boolean result = generateTree(populator, getHandle().getMinecraftWorld().getChunkProvider().generator, pos, random, treeType); populator.refreshTiles(); for (BlockState blockState : populator.getList()) { if (consumer != null) { consumer.accept(blockState); } blockState.update(true, true); } return result; } public boolean generateTree(GeneratorAccessSeed access, ChunkGenerator chunkGenerator, BlockPosition pos, Random random, TreeType treeType) { net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured gen; switch (treeType) { case BIG_TREE: gen = BiomeDecoratorGroups.FANCY_OAK; break; case BIRCH: gen = BiomeDecoratorGroups.BIRCH; break; case REDWOOD: gen = BiomeDecoratorGroups.SPRUCE; break; case TALL_REDWOOD: gen = BiomeDecoratorGroups.PINE; break; case JUNGLE: gen = BiomeDecoratorGroups.MEGA_JUNGLE_TREE; break; case SMALL_JUNGLE: gen = BiomeDecoratorGroups.JUNGLE_TREE_NO_VINE; break; case COCOA_TREE: gen = BiomeDecoratorGroups.JUNGLE_TREE; break; case JUNGLE_BUSH: gen = BiomeDecoratorGroups.JUNGLE_BUSH; break; case RED_MUSHROOM: gen = BiomeDecoratorGroups.HUGE_RED_MUSHROOM; break; case BROWN_MUSHROOM: gen = BiomeDecoratorGroups.HUGE_BROWN_MUSHROOM; break; case SWAMP: gen = BiomeDecoratorGroups.SWAMP_OAK; break; case ACACIA: gen = BiomeDecoratorGroups.ACACIA; break; case DARK_OAK: gen = BiomeDecoratorGroups.DARK_OAK; break; case MEGA_REDWOOD: gen = BiomeDecoratorGroups.MEGA_PINE; break; case TALL_BIRCH: gen = BiomeDecoratorGroups.SUPER_BIRCH_BEES_0002; break; case CHORUS_PLANT: ((BlockChorusFlower) Blocks.CHORUS_FLOWER).a(access, pos, random, 8); return true; case CRIMSON_FUNGUS: gen = BiomeDecoratorGroups.CRIMSON_FUNGI_PLANTED; break; case WARPED_FUNGUS: gen = BiomeDecoratorGroups.WARPED_FUNGI_PLANTED; break; case AZALEA: gen = BiomeDecoratorGroups.AZALEA_TREE; break; case TREE: default: gen = BiomeDecoratorGroups.OAK; break; } return gen.feature.generate(new FeaturePlaceContext(access, chunkGenerator, random, pos, gen.config)); } @Override public Entity spawnEntity(Location location, EntityType entityType) { return spawn(location, entityType.getEntityClass()); } @Override public Entity spawnEntity(Location loc, EntityType type, boolean randomizeData) { return spawn(loc, type.getEntityClass(), null, CreatureSpawnEvent.SpawnReason.CUSTOM, randomizeData); } @Override public List getEntities() { List list = new ArrayList(); getNMSEntities().forEach(entity -> { Entity bukkitEntity = entity.getBukkitEntity(); // Assuming that bukkitEntity isn't null if (bukkitEntity != null && (!isNormalWorld() || bukkitEntity.isValid())) { list.add(bukkitEntity); } }); return list; } @Override public List getLivingEntities() { List list = new ArrayList(); getNMSEntities().forEach(entity -> { Entity bukkitEntity = entity.getBukkitEntity(); // Assuming that bukkitEntity isn't null if (bukkitEntity != null && bukkitEntity instanceof LivingEntity && (!isNormalWorld() || bukkitEntity.isValid())) { list.add((LivingEntity) bukkitEntity); } }); return list; } @Override @SuppressWarnings("unchecked") public Collection getEntitiesByClass(Class clazz) { Collection list = new ArrayList(); getNMSEntities().forEach(entity -> { Entity bukkitEntity = entity.getBukkitEntity(); if (bukkitEntity == null) { return; } Class bukkitClass = bukkitEntity.getClass(); if (clazz.isAssignableFrom(bukkitClass) && (!isNormalWorld() || bukkitEntity.isValid())) { list.add((T) bukkitEntity); } }); return list; } @Override public Collection getEntitiesByClasses(Class... classes) { Collection list = new ArrayList(); getNMSEntities().forEach(entity -> { Entity bukkitEntity = entity.getBukkitEntity(); if (bukkitEntity == null) { return; } Class bukkitClass = bukkitEntity.getClass(); for (Class clazz : classes) { if (clazz.isAssignableFrom(bukkitClass)) { if (!isNormalWorld() || bukkitEntity.isValid()) { list.add(bukkitEntity); } break; } } }); return list; } public abstract Iterable getNMSEntities(); @Override public T spawn(Location location, Class clazz) throws IllegalArgumentException { return spawn(location, clazz, null, CreatureSpawnEvent.SpawnReason.CUSTOM); } @Override public T spawn(Location location, Class clazz, Consumer function) throws IllegalArgumentException { return spawn(location, clazz, function, CreatureSpawnEvent.SpawnReason.CUSTOM); } @Override public T spawn(Location location, Class clazz, boolean randomizeData, Consumer function) throws IllegalArgumentException { return spawn(location, clazz, function, CreatureSpawnEvent.SpawnReason.CUSTOM, randomizeData); } public T spawn(Location location, Class clazz, Consumer function, CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { return spawn(location, clazz, function, reason, true); } public T spawn(Location location, Class clazz, Consumer function, CreatureSpawnEvent.SpawnReason reason, boolean randomizeData) throws IllegalArgumentException { net.minecraft.world.entity.Entity entity = createEntity(location, clazz); return addEntity(entity, reason, function, randomizeData); } @SuppressWarnings("unchecked") public T addEntity(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { return addEntity(entity, reason, null, true); } @SuppressWarnings("unchecked") public T addEntity(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason, Consumer function, boolean randomizeData) throws IllegalArgumentException { Preconditions.checkArgument(entity != null, "Cannot spawn null entity"); if (randomizeData && entity instanceof EntityInsentient) { ((EntityInsentient) entity).prepare(getHandle(), getHandle().getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, null); } if (!isNormalWorld()) { entity.generation = true; } if (function != null) { function.accept((T) entity.getBukkitEntity()); } addEntityToWorld(entity, reason); return (T) entity.getBukkitEntity(); } public abstract void addEntityToWorld(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason); @SuppressWarnings("unchecked") public net.minecraft.world.entity.Entity createEntity(Location location, Class clazz) throws IllegalArgumentException { if (location == null || clazz == null) { throw new IllegalArgumentException("Location or entity class cannot be null"); } net.minecraft.world.entity.Entity entity = null; net.minecraft.world.level.World world = getHandle().getMinecraftWorld(); double x = location.getX(); double y = location.getY(); double z = location.getZ(); float pitch = location.getPitch(); float yaw = location.getYaw(); // order is important for some of these if (Boat.class.isAssignableFrom(clazz)) { entity = new EntityBoat(world, x, y, z); entity.setPositionRotation(x, y, z, yaw, pitch); } else if (FallingBlock.class.isAssignableFrom(clazz)) { entity = new EntityFallingBlock(world, x, y, z, getHandle().getType(new BlockPosition(x, y, z))); } else if (Projectile.class.isAssignableFrom(clazz)) { if (Snowball.class.isAssignableFrom(clazz)) { entity = new EntitySnowball(world, x, y, z); } else if (Egg.class.isAssignableFrom(clazz)) { entity = new EntityEgg(world, x, y, z); } else if (AbstractArrow.class.isAssignableFrom(clazz)) { if (TippedArrow.class.isAssignableFrom(clazz)) { entity = EntityTypes.ARROW.a(world); ((EntityTippedArrow) entity).setType(CraftPotionUtil.fromBukkit(new PotionData(PotionType.WATER, false, false))); } else if (SpectralArrow.class.isAssignableFrom(clazz)) { entity = EntityTypes.SPECTRAL_ARROW.a(world); } else if (Trident.class.isAssignableFrom(clazz)) { entity = EntityTypes.TRIDENT.a(world); } else { entity = EntityTypes.ARROW.a(world); } entity.setPositionRotation(x, y, z, 0, 0); } else if (ThrownExpBottle.class.isAssignableFrom(clazz)) { entity = EntityTypes.EXPERIENCE_BOTTLE.a(world); entity.setPositionRotation(x, y, z, 0, 0); } else if (EnderPearl.class.isAssignableFrom(clazz)) { entity = EntityTypes.ENDER_PEARL.a(world); entity.setPositionRotation(x, y, z, 0, 0); } else if (ThrownPotion.class.isAssignableFrom(clazz)) { if (LingeringPotion.class.isAssignableFrom(clazz)) { entity = new EntityPotion(world, x, y, z); ((EntityPotion) entity).setItem(CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.LINGERING_POTION, 1))); } else { entity = new EntityPotion(world, x, y, z); ((EntityPotion) entity).setItem(CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.SPLASH_POTION, 1))); } } else if (Fireball.class.isAssignableFrom(clazz)) { if (SmallFireball.class.isAssignableFrom(clazz)) { entity = EntityTypes.SMALL_FIREBALL.a(world); } else if (WitherSkull.class.isAssignableFrom(clazz)) { entity = EntityTypes.WITHER_SKULL.a(world); } else if (DragonFireball.class.isAssignableFrom(clazz)) { entity = EntityTypes.DRAGON_FIREBALL.a(world); } else { entity = EntityTypes.FIREBALL.a(world); } entity.setPositionRotation(x, y, z, yaw, pitch); Vector direction = location.getDirection().multiply(10); ((EntityFireball) entity).setDirection(direction.getX(), direction.getY(), direction.getZ()); } else if (ShulkerBullet.class.isAssignableFrom(clazz)) { entity = EntityTypes.SHULKER_BULLET.a(world); entity.setPositionRotation(x, y, z, yaw, pitch); } else if (LlamaSpit.class.isAssignableFrom(clazz)) { entity = EntityTypes.LLAMA_SPIT.a(world); entity.setPositionRotation(x, y, z, yaw, pitch); } else if (Firework.class.isAssignableFrom(clazz)) { entity = new EntityFireworks(world, x, y, z, net.minecraft.world.item.ItemStack.EMPTY); } } else if (Minecart.class.isAssignableFrom(clazz)) { if (PoweredMinecart.class.isAssignableFrom(clazz)) { entity = new EntityMinecartFurnace(world, x, y, z); } else if (StorageMinecart.class.isAssignableFrom(clazz)) { entity = new EntityMinecartChest(world, x, y, z); } else if (ExplosiveMinecart.class.isAssignableFrom(clazz)) { entity = new EntityMinecartTNT(world, x, y, z); } else if (HopperMinecart.class.isAssignableFrom(clazz)) { entity = new EntityMinecartHopper(world, x, y, z); } else if (SpawnerMinecart.class.isAssignableFrom(clazz)) { entity = new EntityMinecartMobSpawner(world, x, y, z); } else if (CommandMinecart.class.isAssignableFrom(clazz)) { entity = new EntityMinecartCommandBlock(world, x, y, z); } else { // Default to rideable minecart for pre-rideable compatibility entity = new EntityMinecartRideable(world, x, y, z); } } else if (EnderSignal.class.isAssignableFrom(clazz)) { entity = new EntityEnderSignal(world, x, y, z); } else if (EnderCrystal.class.isAssignableFrom(clazz)) { entity = EntityTypes.END_CRYSTAL.a(world); entity.setPositionRotation(x, y, z, 0, 0); } else if (LivingEntity.class.isAssignableFrom(clazz)) { if (Chicken.class.isAssignableFrom(clazz)) { entity = EntityTypes.CHICKEN.a(world); } else if (Cow.class.isAssignableFrom(clazz)) { if (MushroomCow.class.isAssignableFrom(clazz)) { entity = EntityTypes.MOOSHROOM.a(world); } else { entity = EntityTypes.COW.a(world); } } else if (Golem.class.isAssignableFrom(clazz)) { if (Snowman.class.isAssignableFrom(clazz)) { entity = EntityTypes.SNOW_GOLEM.a(world); } else if (IronGolem.class.isAssignableFrom(clazz)) { entity = EntityTypes.IRON_GOLEM.a(world); } else if (Shulker.class.isAssignableFrom(clazz)) { entity = EntityTypes.SHULKER.a(world); } } else if (Creeper.class.isAssignableFrom(clazz)) { entity = EntityTypes.CREEPER.a(world); } else if (Ghast.class.isAssignableFrom(clazz)) { entity = EntityTypes.GHAST.a(world); } else if (Pig.class.isAssignableFrom(clazz)) { entity = EntityTypes.PIG.a(world); } else if (Player.class.isAssignableFrom(clazz)) { // need a net server handler for this one } else if (Sheep.class.isAssignableFrom(clazz)) { entity = EntityTypes.SHEEP.a(world); } else if (AbstractHorse.class.isAssignableFrom(clazz)) { if (ChestedHorse.class.isAssignableFrom(clazz)) { if (Donkey.class.isAssignableFrom(clazz)) { entity = EntityTypes.DONKEY.a(world); } else if (Mule.class.isAssignableFrom(clazz)) { entity = EntityTypes.MULE.a(world); } else if (Llama.class.isAssignableFrom(clazz)) { if (TraderLlama.class.isAssignableFrom(clazz)) { entity = EntityTypes.TRADER_LLAMA.a(world); } else { entity = EntityTypes.LLAMA.a(world); } } } else if (SkeletonHorse.class.isAssignableFrom(clazz)) { entity = EntityTypes.SKELETON_HORSE.a(world); } else if (ZombieHorse.class.isAssignableFrom(clazz)) { entity = EntityTypes.ZOMBIE_HORSE.a(world); } else { entity = EntityTypes.HORSE.a(world); } } else if (AbstractSkeleton.class.isAssignableFrom(clazz)) { if (Stray.class.isAssignableFrom(clazz)) { entity = EntityTypes.STRAY.a(world); } else if (WitherSkeleton.class.isAssignableFrom(clazz)) { entity = EntityTypes.WITHER_SKELETON.a(world); } else if (Skeleton.class.isAssignableFrom(clazz)) { entity = EntityTypes.SKELETON.a(world); } } else if (Slime.class.isAssignableFrom(clazz)) { if (MagmaCube.class.isAssignableFrom(clazz)) { entity = EntityTypes.MAGMA_CUBE.a(world); } else { entity = EntityTypes.SLIME.a(world); } } else if (Spider.class.isAssignableFrom(clazz)) { if (CaveSpider.class.isAssignableFrom(clazz)) { entity = EntityTypes.CAVE_SPIDER.a(world); } else { entity = EntityTypes.SPIDER.a(world); } } else if (Squid.class.isAssignableFrom(clazz)) { if (GlowSquid.class.isAssignableFrom(clazz)) { entity = EntityTypes.GLOW_SQUID.a(world); } else { entity = EntityTypes.SQUID.a(world); } } else if (Tameable.class.isAssignableFrom(clazz)) { if (Wolf.class.isAssignableFrom(clazz)) { entity = EntityTypes.WOLF.a(world); } else if (Parrot.class.isAssignableFrom(clazz)) { entity = EntityTypes.PARROT.a(world); } else if (Cat.class.isAssignableFrom(clazz)) { entity = EntityTypes.CAT.a(world); } } else if (PigZombie.class.isAssignableFrom(clazz)) { entity = EntityTypes.ZOMBIFIED_PIGLIN.a(world); } else if (Zombie.class.isAssignableFrom(clazz)) { if (Husk.class.isAssignableFrom(clazz)) { entity = EntityTypes.HUSK.a(world); } else if (ZombieVillager.class.isAssignableFrom(clazz)) { entity = EntityTypes.ZOMBIE_VILLAGER.a(world); } else if (Drowned.class.isAssignableFrom(clazz)) { entity = EntityTypes.DROWNED.a(world); } else { entity = new EntityZombie(world); } } else if (Giant.class.isAssignableFrom(clazz)) { entity = EntityTypes.GIANT.a(world); } else if (Silverfish.class.isAssignableFrom(clazz)) { entity = EntityTypes.SILVERFISH.a(world); } else if (Enderman.class.isAssignableFrom(clazz)) { entity = EntityTypes.ENDERMAN.a(world); } else if (Blaze.class.isAssignableFrom(clazz)) { entity = EntityTypes.BLAZE.a(world); } else if (AbstractVillager.class.isAssignableFrom(clazz)) { if (Villager.class.isAssignableFrom(clazz)) { entity = EntityTypes.VILLAGER.a(world); } else if (WanderingTrader.class.isAssignableFrom(clazz)) { entity = EntityTypes.WANDERING_TRADER.a(world); } } else if (Witch.class.isAssignableFrom(clazz)) { entity = EntityTypes.WITCH.a(world); } else if (Wither.class.isAssignableFrom(clazz)) { entity = EntityTypes.WITHER.a(world); } else if (ComplexLivingEntity.class.isAssignableFrom(clazz)) { if (EnderDragon.class.isAssignableFrom(clazz)) { if (isNormalWorld()) { entity = EntityTypes.ENDER_DRAGON.a(getHandle().getMinecraftWorld()); } else { throw new IllegalArgumentException("Cannot spawn entity " + clazz.getName() + " during world generation"); } } } else if (Ambient.class.isAssignableFrom(clazz)) { if (Bat.class.isAssignableFrom(clazz)) { entity = EntityTypes.BAT.a(world); } } else if (Rabbit.class.isAssignableFrom(clazz)) { entity = EntityTypes.RABBIT.a(world); } else if (Endermite.class.isAssignableFrom(clazz)) { entity = EntityTypes.ENDERMITE.a(world); } else if (Guardian.class.isAssignableFrom(clazz)) { if (ElderGuardian.class.isAssignableFrom(clazz)) { entity = EntityTypes.ELDER_GUARDIAN.a(world); } else { entity = EntityTypes.GUARDIAN.a(world); } } else if (ArmorStand.class.isAssignableFrom(clazz)) { entity = new EntityArmorStand(world, x, y, z); } else if (PolarBear.class.isAssignableFrom(clazz)) { entity = EntityTypes.POLAR_BEAR.a(world); } else if (Vex.class.isAssignableFrom(clazz)) { entity = EntityTypes.VEX.a(world); } else if (Illager.class.isAssignableFrom(clazz)) { if (Spellcaster.class.isAssignableFrom(clazz)) { if (Evoker.class.isAssignableFrom(clazz)) { entity = EntityTypes.EVOKER.a(world); } else if (Illusioner.class.isAssignableFrom(clazz)) { entity = EntityTypes.ILLUSIONER.a(world); } } else if (Vindicator.class.isAssignableFrom(clazz)) { entity = EntityTypes.VINDICATOR.a(world); } else if (Pillager.class.isAssignableFrom(clazz)) { entity = EntityTypes.PILLAGER.a(world); } } else if (Turtle.class.isAssignableFrom(clazz)) { entity = EntityTypes.TURTLE.a(world); } else if (Phantom.class.isAssignableFrom(clazz)) { entity = EntityTypes.PHANTOM.a(world); } else if (Fish.class.isAssignableFrom(clazz)) { if (Cod.class.isAssignableFrom(clazz)) { entity = EntityTypes.COD.a(world); } else if (PufferFish.class.isAssignableFrom(clazz)) { entity = EntityTypes.PUFFERFISH.a(world); } else if (Salmon.class.isAssignableFrom(clazz)) { entity = EntityTypes.SALMON.a(world); } else if (TropicalFish.class.isAssignableFrom(clazz)) { entity = EntityTypes.TROPICAL_FISH.a(world); } } else if (Dolphin.class.isAssignableFrom(clazz)) { entity = EntityTypes.DOLPHIN.a(world); } else if (Ocelot.class.isAssignableFrom(clazz)) { entity = EntityTypes.OCELOT.a(world); } else if (Ravager.class.isAssignableFrom(clazz)) { entity = EntityTypes.RAVAGER.a(world); } else if (Panda.class.isAssignableFrom(clazz)) { entity = EntityTypes.PANDA.a(world); } else if (Fox.class.isAssignableFrom(clazz)) { entity = EntityTypes.FOX.a(world); } else if (Bee.class.isAssignableFrom(clazz)) { entity = EntityTypes.BEE.a(world); } else if (Hoglin.class.isAssignableFrom(clazz)) { entity = EntityTypes.HOGLIN.a(world); } else if (Piglin.class.isAssignableFrom(clazz)) { entity = EntityTypes.PIGLIN.a(world); } else if (PiglinBrute.class.isAssignableFrom(clazz)) { entity = EntityTypes.PIGLIN_BRUTE.a(world); } else if (Strider.class.isAssignableFrom(clazz)) { entity = EntityTypes.STRIDER.a(world); } else if (Zoglin.class.isAssignableFrom(clazz)) { entity = EntityTypes.ZOGLIN.a(world); } else if (Axolotl.class.isAssignableFrom(clazz)) { entity = EntityTypes.AXOLOTL.a(world); } else if (Goat.class.isAssignableFrom(clazz)) { entity = EntityTypes.GOAT.a(world); } if (entity != null) { entity.setLocation(x, y, z, yaw, pitch); entity.setHeadRotation(yaw); // SPIGOT-3587 } } else if (Hanging.class.isAssignableFrom(clazz)) { BlockFace face = BlockFace.SELF; int width = 16; // 1 full block, also painting smallest size. int height = 16; // 1 full block, also painting smallest size. if (ItemFrame.class.isAssignableFrom(clazz)) { width = 12; height = 12; } else if (LeashHitch.class.isAssignableFrom(clazz)) { width = 9; height = 9; } BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; final BlockPosition pos = new BlockPosition(x, y, z); for (BlockFace dir : faces) { IBlockData nmsBlock = getHandle().getType(pos.shift(CraftBlock.blockFaceToNotch(dir))); if (nmsBlock.getMaterial().isBuildable() || BlockDiodeAbstract.isDiode(nmsBlock)) { boolean taken = false; AxisAlignedBB bb = (ItemFrame.class.isAssignableFrom(clazz)) ? EntityItemFrame.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).opposite(), width, height) : EntityHanging.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).opposite(), width, height); List list = (List) getHandle().getEntities(null, bb); for (Iterator it = list.iterator(); !taken && it.hasNext();) { net.minecraft.world.entity.Entity e = it.next(); if (e instanceof EntityHanging) { taken = true; // Hanging entities do not like hanging entities which intersect them. } } if (!taken) { face = dir; break; } } } if (LeashHitch.class.isAssignableFrom(clazz)) { entity = new EntityLeash(world, new BlockPosition(x, y, z)); } else { // No valid face found Preconditions.checkArgument(face != BlockFace.SELF, "Cannot spawn hanging entity for %s at %s (no free face)", clazz.getName(), location); EnumDirection dir = CraftBlock.blockFaceToNotch(face).opposite(); if (Painting.class.isAssignableFrom(clazz)) { if (isNormalWorld()) { entity = new EntityPainting(getHandle().getMinecraftWorld(), new BlockPosition(x, y, z), dir); } else { entity = new EntityPainting(EntityTypes.PAINTING, getHandle().getMinecraftWorld()); entity.setLocation(x, y, z, yaw, pitch); ((EntityPainting) entity).setDirection(dir); } } else if (ItemFrame.class.isAssignableFrom(clazz)) { if (GlowItemFrame.class.isAssignableFrom(clazz)) { entity = new net.minecraft.world.entity.decoration.GlowItemFrame(world, new BlockPosition(x, y, z), dir); } else { entity = new EntityItemFrame(world, new BlockPosition(x, y, z), dir); } } } // survives call does not work during world generation if (entity != null && isNormalWorld() && !((EntityHanging) entity).survives()) { throw new IllegalArgumentException("Cannot spawn hanging entity for " + clazz.getName() + " at " + location); } } else if (TNTPrimed.class.isAssignableFrom(clazz)) { entity = new EntityTNTPrimed(world, x, y, z, null); } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { entity = new EntityExperienceOrb(world, x, y, z, 0); } else if (LightningStrike.class.isAssignableFrom(clazz)) { entity = EntityTypes.LIGHTNING_BOLT.a(world); entity.teleportAndSync(location.getX(), location.getY(), location.getZ()); } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { entity = new EntityAreaEffectCloud(world, x, y, z); } else if (EvokerFangs.class.isAssignableFrom(clazz)) { entity = new EntityEvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); } else if (Marker.class.isAssignableFrom(clazz)) { entity = EntityTypes.MARKER.a(world); entity.setPosition(x, y, z); } if (entity != null) { return entity; } throw new IllegalArgumentException("Cannot spawn an entity for " + clazz.getName()); } }