2020-07-22 06:23:34 +01:00
package net.minecraft.world.level ;
import java.util.AbstractList ;
import org.apache.logging.log4j.LogManager ;
import java.util.function.Function ;
import net.minecraft.nbt.Tag ;
import net.minecraft.util.WeighedRandom ;
import java.util.Iterator ;
import net.minecraft.nbt.ListTag ;
import java.util.Optional ;
import net.minecraft.nbt.CompoundTag ;
import net.minecraft.world.entity.SpawnGroupData ;
import net.minecraft.world.entity.Mob ;
import net.minecraft.world.phys.AABB ;
import net.minecraft.world.entity.SpawnPlacements ;
import net.minecraft.world.entity.MobSpawnType ;
import net.minecraft.core.particles.ParticleOptions ;
import net.minecraft.core.particles.ParticleTypes ;
import net.minecraft.core.Registry ;
import net.minecraft.world.entity.EntityType ;
import net.minecraft.core.BlockPos ;
import net.minecraft.ResourceLocationException ;
import net.minecraft.util.StringUtil ;
import net.minecraft.resources.ResourceLocation ;
import com.google.common.collect.Lists ;
2020-07-22 06:25:47 +01:00
import javax.annotation.Nullable ;
2020-07-22 06:23:34 +01:00
import net.minecraft.world.entity.Entity ;
import java.util.List ;
import org.apache.logging.log4j.Logger ;
public abstract class BaseSpawner {
private static final Logger LOGGER ;
private int spawnDelay ;
private final List < SpawnData > spawnPotentials ;
private SpawnData nextSpawnData ;
private double spin ;
private double oSpin ;
private int minSpawnDelay ;
private int maxSpawnDelay ;
private int spawnCount ;
2020-07-22 06:25:47 +01:00
@Nullable
2020-07-22 06:23:34 +01:00
private Entity displayEntity ;
private int maxNearbyEntities ;
private int requiredPlayerRange ;
private int spawnRange ;
public BaseSpawner ( ) {
this . spawnDelay = 20 ;
this . spawnPotentials = Lists . newArrayList ( ) ;
this . nextSpawnData = new SpawnData ( ) ;
this . minSpawnDelay = 200 ;
this . maxSpawnDelay = 800 ;
this . spawnCount = 4 ;
this . maxNearbyEntities = 6 ;
this . requiredPlayerRange = 16 ;
this . spawnRange = 4 ;
}
@Nullable
private ResourceLocation getEntityId ( ) {
final String string2 = this . nextSpawnData . getTag ( ) . getString ( " id " ) ;
try {
return StringUtil . isNullOrEmpty ( string2 ) ? null : new ResourceLocation ( string2 ) ;
}
2020-07-22 06:25:47 +01:00
catch ( ResourceLocationException r3 ) {
final BlockPos fk4 = this . getPos ( ) ;
BaseSpawner . LOGGER . warn ( " Invalid entity id '{}' at spawner {}:[{},{},{}] " , string2 , this . getLevel ( ) . dimension . getType ( ) , fk4 . getX ( ) , fk4 . getY ( ) , fk4 . getZ ( ) ) ;
2020-07-22 06:23:34 +01:00
return null ;
}
}
2020-07-22 06:25:47 +01:00
public void setEntityId ( final EntityType < ? > akr ) {
this . nextSpawnData . getTag ( ) . putString ( " id " , Registry . ENTITY_TYPE . getKey ( akr ) . toString ( ) ) ;
2020-07-22 06:23:34 +01:00
}
private boolean isNearPlayer ( ) {
2020-07-22 06:25:47 +01:00
final BlockPos fk2 = this . getPos ( ) ;
return this . getLevel ( ) . hasNearbyAlivePlayer ( fk2 . getX ( ) + 0 . 5 , fk2 . getY ( ) + 0 . 5 , fk2 . getZ ( ) + 0 . 5 , this . requiredPlayerRange ) ;
2020-07-22 06:23:34 +01:00
}
public void tick ( ) {
if ( ! this . isNearPlayer ( ) ) {
this . oSpin = this . spin ;
return ;
}
2020-07-22 06:25:47 +01:00
final Level bjt2 = this . getLevel ( ) ;
final BlockPos fk3 = this . getPos ( ) ;
if ( bjt2 . isClientSide ) {
final double double4 = fk3 . getX ( ) + ( double ) bjt2 . random . nextFloat ( ) ;
final double double5 = fk3 . getY ( ) + ( double ) bjt2 . random . nextFloat ( ) ;
final double double6 = fk3 . getZ ( ) + ( double ) bjt2 . random . nextFloat ( ) ;
bjt2 . addParticle ( ParticleTypes . SMOKE , double4 , double5 , double6 , 0 . 0 , 0 . 0 , 0 . 0 ) ;
bjt2 . addParticle ( ParticleTypes . FLAME , double4 , double5 , double6 , 0 . 0 , 0 . 0 , 0 . 0 ) ;
2020-07-22 06:23:34 +01:00
if ( this . spawnDelay > 0 ) {
- - this . spawnDelay ;
}
this . oSpin = this . spin ;
this . spin = ( this . spin + 1000 . 0f / ( this . spawnDelay + 200 . 0f ) ) % 360 . 0 ;
}
else {
if ( this . spawnDelay = = - 1 ) {
this . delay ( ) ;
}
if ( this . spawnDelay > 0 ) {
- - this . spawnDelay ;
return ;
}
boolean boolean4 = false ;
for ( int integer5 = 0 ; integer5 < this . spawnCount ; + + integer5 ) {
2020-07-22 06:25:47 +01:00
final CompoundTag jt6 = this . nextSpawnData . getTag ( ) ;
final Optional < EntityType < ? > > optional7 = EntityType . by ( jt6 ) ;
2020-07-22 06:23:34 +01:00
if ( ! optional7 . isPresent ( ) ) {
this . delay ( ) ;
return ;
}
2020-07-22 06:25:47 +01:00
final ListTag jz8 = jt6 . getList ( " Pos " , 6 ) ;
final int integer6 = jz8 . size ( ) ;
final double double7 = ( integer6 > = 1 ) ? jz8 . getDouble ( 0 ) : ( fk3 . getX ( ) + ( bjt2 . random . nextDouble ( ) - bjt2 . random . nextDouble ( ) ) * this . spawnRange + 0 . 5 ) ;
final double double8 = ( integer6 > = 2 ) ? jz8 . getDouble ( 1 ) : ( fk3 . getY ( ) + bjt2 . random . nextInt ( 3 ) - 1 ) ;
final double double9 = ( integer6 > = 3 ) ? jz8 . getDouble ( 2 ) : ( fk3 . getZ ( ) + ( bjt2 . random . nextDouble ( ) - bjt2 . random . nextDouble ( ) ) * this . spawnRange + 0 . 5 ) ;
if ( bjt2 . noCollision ( optional7 . get ( ) . getAABB ( double7 , double8 , double9 ) ) ) {
if ( SpawnPlacements . < Entity > checkSpawnRules ( optional7 . get ( ) , bjt2 . getLevel ( ) , MobSpawnType . SPAWNER , new BlockPos ( double7 , double8 , double9 ) , bjt2 . getRandom ( ) ) ) {
final Entity akn2 = EntityType . loadEntityRecursive ( jt6 , bjt2 , akn - > {
akn . moveTo ( double7 , double8 , double9 , akn . yRot , akn . xRot ) ;
return akn ;
2020-07-22 06:23:34 +01:00
} ) ;
2020-07-22 06:25:47 +01:00
if ( akn2 = = null ) {
2020-07-22 06:23:34 +01:00
this . delay ( ) ;
return ;
}
2020-07-22 06:25:47 +01:00
final int integer7 = bjt2 . < Entity > getEntitiesOfClass ( akn2 . getClass ( ) , new AABB ( fk3 . getX ( ) , fk3 . getY ( ) , fk3 . getZ ( ) , fk3 . getX ( ) + 1 , fk3 . getY ( ) + 1 , fk3 . getZ ( ) + 1 ) . inflate ( this . spawnRange ) ) . size ( ) ;
2020-07-22 06:23:34 +01:00
if ( integer7 > = this . maxNearbyEntities ) {
this . delay ( ) ;
return ;
}
2020-07-22 06:25:47 +01:00
akn2 . moveTo ( akn2 . getX ( ) , akn2 . getY ( ) , akn2 . getZ ( ) , bjt2 . random . nextFloat ( ) * 360 . 0f , 0 . 0f ) ;
if ( akn2 instanceof Mob ) {
final Mob akx18 = ( Mob ) akn2 ;
if ( ! akx18 . checkSpawnRules ( bjt2 , MobSpawnType . SPAWNER ) ) {
2020-07-22 06:23:34 +01:00
continue ;
}
2020-07-22 06:25:47 +01:00
if ( ! akx18 . checkSpawnObstruction ( bjt2 ) ) {
2020-07-22 06:23:34 +01:00
continue ;
}
if ( this . nextSpawnData . getTag ( ) . size ( ) = = 1 & & this . nextSpawnData . getTag ( ) . contains ( " id " , 8 ) ) {
2020-07-22 06:25:47 +01:00
( ( Mob ) akn2 ) . finalizeSpawn ( bjt2 , bjt2 . getCurrentDifficultyAt ( new BlockPos ( akn2 ) ) , MobSpawnType . SPAWNER , null , null ) ;
2020-07-22 06:23:34 +01:00
}
}
2020-07-22 06:25:47 +01:00
this . addWithPassengers ( akn2 ) ;
bjt2 . levelEvent ( 2004 , fk3 , 0 ) ;
if ( akn2 instanceof Mob ) {
( ( Mob ) akn2 ) . spawnAnim ( ) ;
2020-07-22 06:23:34 +01:00
}
boolean4 = true ;
}
}
}
if ( boolean4 ) {
this . delay ( ) ;
}
}
}
2020-07-22 06:25:47 +01:00
private void addWithPassengers ( final Entity akn ) {
if ( ! this . getLevel ( ) . addFreshEntity ( akn ) ) {
2020-07-22 06:23:34 +01:00
return ;
}
2020-07-22 06:25:47 +01:00
for ( final Entity akn2 : akn . getPassengers ( ) ) {
this . addWithPassengers ( akn2 ) ;
2020-07-22 06:23:34 +01:00
}
}
private void delay ( ) {
if ( this . maxSpawnDelay < = this . minSpawnDelay ) {
this . spawnDelay = this . minSpawnDelay ;
}
else {
this . spawnDelay = this . minSpawnDelay + this . getLevel ( ) . random . nextInt ( this . maxSpawnDelay - this . minSpawnDelay ) ;
}
if ( ! this . spawnPotentials . isEmpty ( ) ) {
this . setNextSpawnData ( WeighedRandom . < SpawnData > getRandomItem ( this . getLevel ( ) . random , this . spawnPotentials ) ) ;
}
this . broadcastEvent ( 1 ) ;
}
2020-07-22 06:25:47 +01:00
public void load ( final CompoundTag jt ) {
this . spawnDelay = jt . getShort ( " Delay " ) ;
2020-07-22 06:23:34 +01:00
this . spawnPotentials . clear ( ) ;
2020-07-22 06:25:47 +01:00
if ( jt . contains ( " SpawnPotentials " , 9 ) ) {
final ListTag jz3 = jt . getList ( " SpawnPotentials " , 10 ) ;
for ( int integer4 = 0 ; integer4 < jz3 . size ( ) ; + + integer4 ) {
this . spawnPotentials . add ( new SpawnData ( jz3 . getCompound ( integer4 ) ) ) ;
2020-07-22 06:23:34 +01:00
}
}
2020-07-22 06:25:47 +01:00
if ( jt . contains ( " SpawnData " , 10 ) ) {
this . setNextSpawnData ( new SpawnData ( 1 , jt . getCompound ( " SpawnData " ) ) ) ;
2020-07-22 06:23:34 +01:00
}
else if ( ! this . spawnPotentials . isEmpty ( ) ) {
this . setNextSpawnData ( WeighedRandom . < SpawnData > getRandomItem ( this . getLevel ( ) . random , this . spawnPotentials ) ) ;
}
2020-07-22 06:25:47 +01:00
if ( jt . contains ( " MinSpawnDelay " , 99 ) ) {
this . minSpawnDelay = jt . getShort ( " MinSpawnDelay " ) ;
this . maxSpawnDelay = jt . getShort ( " MaxSpawnDelay " ) ;
this . spawnCount = jt . getShort ( " SpawnCount " ) ;
2020-07-22 06:23:34 +01:00
}
2020-07-22 06:25:47 +01:00
if ( jt . contains ( " MaxNearbyEntities " , 99 ) ) {
this . maxNearbyEntities = jt . getShort ( " MaxNearbyEntities " ) ;
this . requiredPlayerRange = jt . getShort ( " RequiredPlayerRange " ) ;
2020-07-22 06:23:34 +01:00
}
2020-07-22 06:25:47 +01:00
if ( jt . contains ( " SpawnRange " , 99 ) ) {
this . spawnRange = jt . getShort ( " SpawnRange " ) ;
2020-07-22 06:23:34 +01:00
}
if ( this . getLevel ( ) ! = null ) {
this . displayEntity = null ;
}
}
2020-07-22 06:25:47 +01:00
public CompoundTag save ( final CompoundTag jt ) {
final ResourceLocation sm3 = this . getEntityId ( ) ;
if ( sm3 = = null ) {
return jt ;
2020-07-22 06:23:34 +01:00
}
2020-07-22 06:25:47 +01:00
jt . putShort ( " Delay " , ( short ) this . spawnDelay ) ;
jt . putShort ( " MinSpawnDelay " , ( short ) this . minSpawnDelay ) ;
jt . putShort ( " MaxSpawnDelay " , ( short ) this . maxSpawnDelay ) ;
jt . putShort ( " SpawnCount " , ( short ) this . spawnCount ) ;
jt . putShort ( " MaxNearbyEntities " , ( short ) this . maxNearbyEntities ) ;
jt . putShort ( " RequiredPlayerRange " , ( short ) this . requiredPlayerRange ) ;
jt . putShort ( " SpawnRange " , ( short ) this . spawnRange ) ;
jt . put ( " SpawnData " , this . nextSpawnData . getTag ( ) . copy ( ) ) ;
final ListTag jz4 = new ListTag ( ) ;
2020-07-22 06:23:34 +01:00
if ( this . spawnPotentials . isEmpty ( ) ) {
2020-07-22 06:25:47 +01:00
( ( AbstractList < CompoundTag > ) jz4 ) . add ( this . nextSpawnData . save ( ) ) ;
2020-07-22 06:23:34 +01:00
}
else {
2020-07-22 06:25:47 +01:00
for ( final SpawnData bkh6 : this . spawnPotentials ) {
( ( AbstractList < CompoundTag > ) jz4 ) . add ( bkh6 . save ( ) ) ;
2020-07-22 06:23:34 +01:00
}
}
2020-07-22 06:25:47 +01:00
jt . put ( " SpawnPotentials " , jz4 ) ;
return jt ;
2020-07-22 06:23:34 +01:00
}
2020-07-22 06:25:47 +01:00
@Nullable
2020-07-22 06:23:34 +01:00
public Entity getOrCreateDisplayEntity ( ) {
if ( this . displayEntity = = null ) {
this . displayEntity = EntityType . loadEntityRecursive ( this . nextSpawnData . getTag ( ) , this . getLevel ( ) , Function . < Entity > identity ( ) ) ;
if ( this . nextSpawnData . getTag ( ) . size ( ) = = 1 & & this . nextSpawnData . getTag ( ) . contains ( " id " , 8 ) & & this . displayEntity instanceof Mob ) {
( ( Mob ) this . displayEntity ) . finalizeSpawn ( this . getLevel ( ) , this . getLevel ( ) . getCurrentDifficultyAt ( new BlockPos ( this . displayEntity ) ) , MobSpawnType . SPAWNER , null , null ) ;
}
}
return this . displayEntity ;
}
public boolean onEventTriggered ( final int integer ) {
if ( integer = = 1 & & this . getLevel ( ) . isClientSide ) {
this . spawnDelay = this . minSpawnDelay ;
return true ;
}
return false ;
}
2020-07-22 06:25:47 +01:00
public void setNextSpawnData ( final SpawnData bkh ) {
this . nextSpawnData = bkh ;
2020-07-22 06:23:34 +01:00
}
public abstract void broadcastEvent ( final int integer ) ;
public abstract Level getLevel ( ) ;
public abstract BlockPos getPos ( ) ;
public double getSpin ( ) {
return this . spin ;
}
public double getoSpin ( ) {
return this . oSpin ;
}
static {
LOGGER = LogManager . getLogger ( ) ;
}
}