mirror of
https://github.com/FatherToast/SpecialMobs.git
synced 2025-04-25 14:55:03 +00:00
Husk -> Zombie conversion; plus lib stuff
This commit is contained in:
parent
b9c51a20c2
commit
daaeda3f6e
31 changed files with 361 additions and 29 deletions
|
@ -431,7 +431,7 @@ public class BestiaryInfo {
|
||||||
//--------------- Creature Type Templates ----------------
|
//--------------- Creature Type Templates ----------------
|
||||||
|
|
||||||
/** Sets the standard species stats implied by being undead. */
|
/** Sets the standard species stats implied by being undead. */
|
||||||
public Builder undead() { return effectImmune( Effects.REGENERATION, Effects.POISON ); }
|
public Builder undead() { return drownImmune().effectImmune( Effects.REGENERATION, Effects.POISON ); }
|
||||||
|
|
||||||
/** Sets the standard species stats implied by being a spider. */
|
/** Sets the standard species stats implied by being a spider. */
|
||||||
public Builder spider() { return webImmune().effectImmune( Effects.POISON ); }
|
public Builder spider() { return webImmune().effectImmune( Effects.POISON ); }
|
||||||
|
|
|
@ -197,9 +197,14 @@ public class MobFamily<T extends LivingEntity, V extends FamilyConfig> {
|
||||||
|
|
||||||
/** Pick a new species from this family, based on the location. */
|
/** Pick a new species from this family, based on the location. */
|
||||||
public Species<? extends T> nextVariant( World world, @Nullable BlockPos pos ) {
|
public Species<? extends T> nextVariant( World world, @Nullable BlockPos pos ) {
|
||||||
final Species<?> species = config.GENERAL.specialVariantList.next( world.random, world, pos );
|
return nextVariant( world, pos, null, vanillaReplacement );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pick a new species from this family, based on the location. */
|
||||||
|
public Species<? extends T> nextVariant( World world, @Nullable BlockPos pos, @Nullable Function<Species<?>, Boolean> selector, Species<? extends T> fallback ) {
|
||||||
|
final Species<?> species = config.GENERAL.specialVariantList.next( world.random, world, pos, selector );
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return species == null ? vanillaReplacement : (Species<? extends T>) species;
|
return species == null ? fallback : (Species<? extends T>) species;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a config field with a double value.
|
* Represents a config field with a double value.
|
||||||
|
@ -214,12 +215,19 @@ public class DoubleField extends AbstractConfigField {
|
||||||
|
|
||||||
/** @return Returns a random item from this weighted list. Null if none of the items have a positive weight. */
|
/** @return Returns a random item from this weighted list. Null if none of the items have a positive weight. */
|
||||||
@Nullable
|
@Nullable
|
||||||
public T next( Random random, World world, @Nullable BlockPos pos ) {
|
public T next( Random random, World world, @Nullable BlockPos pos ) { return next( random, world, pos, null ); }
|
||||||
|
|
||||||
|
/** @return Returns a random item from this weighted list. Null if none of the items have a positive weight. */
|
||||||
|
@Nullable
|
||||||
|
public T next( Random random, World world, @Nullable BlockPos pos, @Nullable Function<T, Boolean> selector ) {
|
||||||
// Due to the 'nebulous' nature of environment-based weights, we must recalculate weights for EVERY call
|
// Due to the 'nebulous' nature of environment-based weights, we must recalculate weights for EVERY call
|
||||||
final double[] weights = new double[UNDERLYING_LIST.size()];
|
final double[] weights = new double[UNDERLYING_LIST.size()];
|
||||||
double targetWeight = 0.0;
|
double targetWeight = 0.0;
|
||||||
for( int i = 0; i < weights.length; i++ ) {
|
for( int i = 0; i < weights.length; i++ ) {
|
||||||
targetWeight += weights[i] = UNDERLYING_LIST.get( i ).WEIGHT.get( world, pos );
|
final Entry<T> entry = UNDERLYING_LIST.get( i );
|
||||||
|
if( selector == null || selector.apply( entry.VALUE ) ) {
|
||||||
|
targetWeight += weights[i] = entry.WEIGHT.get( world, pos );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( targetWeight <= 0.0 ) return null;
|
if( targetWeight <= 0.0 ) return null;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package fathertoast.specialmobs.common.config.species;
|
||||||
|
|
||||||
|
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||||
|
import fathertoast.specialmobs.common.config.Config;
|
||||||
|
import fathertoast.specialmobs.common.config.field.DoubleField;
|
||||||
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
|
import fathertoast.specialmobs.common.config.file.ToastConfigSpec;
|
||||||
|
import fathertoast.specialmobs.common.config.util.ConfigUtil;
|
||||||
|
import fathertoast.specialmobs.common.config.util.EnvironmentEntry;
|
||||||
|
import fathertoast.specialmobs.common.config.util.EnvironmentList;
|
||||||
|
|
||||||
|
public class HuskZombieSpeciesConfig extends ZombieSpeciesConfig {
|
||||||
|
|
||||||
|
public final Husk HUSK;
|
||||||
|
|
||||||
|
/** Builds the config spec that should be used for this config. */
|
||||||
|
public HuskZombieSpeciesConfig( MobFamily.Species<?> species, double bowChance, double shieldChance ) {
|
||||||
|
super( species, bowChance, shieldChance );
|
||||||
|
|
||||||
|
HUSK = new Husk( SPEC, species, speciesName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Husk extends Config.AbstractCategory {
|
||||||
|
|
||||||
|
public final DoubleField.EnvironmentSensitive convertVariantChance;
|
||||||
|
|
||||||
|
Husk( ToastConfigSpec parent, MobFamily.Species<?> species, String speciesName ) {
|
||||||
|
super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ),
|
||||||
|
"Options specific to " + speciesName + "." );
|
||||||
|
|
||||||
|
convertVariantChance = new DoubleField.EnvironmentSensitive(
|
||||||
|
SPEC.define( new DoubleField( "special_variant_chance.base", 0.33, DoubleField.Range.PERCENT,
|
||||||
|
"The chance for " + speciesName + " to convert to a special zombie variant when drowned." ) ),
|
||||||
|
SPEC.define( new EnvironmentListField( "special_variant_chance.exceptions", new EnvironmentList(
|
||||||
|
EnvironmentEntry.builder( 0.66F ).atMaxMoonLight().build() ).setRange( DoubleField.Range.PERCENT ),
|
||||||
|
"The chance for " + speciesName + " to convert to a special zombie variant when drowned while specific environmental conditions are met." ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ public class SpecialMobs {
|
||||||
* - potions
|
* - potions
|
||||||
* - vulnerability (opposite of resistance)
|
* - vulnerability (opposite of resistance)
|
||||||
* ? gravity (opposite of levitation)
|
* ? gravity (opposite of levitation)
|
||||||
* o entities
|
* - entities
|
||||||
* - nbt-driven capabilities (special mob data)
|
* - nbt-driven capabilities (special mob data)
|
||||||
* - fish hook
|
* - fish hook
|
||||||
* - bug spit
|
* - bug spit
|
||||||
|
@ -54,7 +54,7 @@ public class SpecialMobs {
|
||||||
* - monster families (see doc for specifics)
|
* - monster families (see doc for specifics)
|
||||||
* - creepers
|
* - creepers
|
||||||
* - chance to spawn charged during thunderstorms
|
* - chance to spawn charged during thunderstorms
|
||||||
* + scope
|
* + scope - perhaps delay this until 1.18 where spyglasses will be in the game
|
||||||
* - zombies
|
* - zombies
|
||||||
* o villager infection (is this still reasonably applicable?)
|
* o villager infection (is this still reasonably applicable?)
|
||||||
* + transformations (husk -> any other non-water-sensitive zombie -> any drowned)
|
* + transformations (husk -> any other non-water-sensitive zombie -> any drowned)
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class SpecialGhastFireballAttackGoal extends Goal {
|
||||||
if( target.distanceToSqr( ghast ) < data.getRangedAttackMaxRange() * data.getRangedAttackMaxRange() && ghast.canSee( target ) ) {
|
if( target.distanceToSqr( ghast ) < data.getRangedAttackMaxRange() * data.getRangedAttackMaxRange() && ghast.canSee( target ) ) {
|
||||||
chargeTime++;
|
chargeTime++;
|
||||||
if( chargeTime == (data.getRangedAttackCooldown() >> 1) && !ghast.isSilent() ) {
|
if( chargeTime == (data.getRangedAttackCooldown() >> 1) && !ghast.isSilent() ) {
|
||||||
ghast.level.levelEvent( null, References.EVENT_GHAST_WARN, ghast.blockPosition(), 0 );
|
References.LevelEvent.GHAST_WARN.play( ghast );
|
||||||
}
|
}
|
||||||
if( chargeTime >= data.getRangedAttackCooldown() ) {
|
if( chargeTime >= data.getRangedAttackCooldown() ) {
|
||||||
ghast.performRangedAttack( target, 1.0F );
|
ghast.performRangedAttack( target, 1.0F );
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class HellfireBlazeEntity extends _SpecialBlazeEntity {
|
||||||
/** Called to attack the target with a ranged attack. */
|
/** Called to attack the target with a ranged attack. */
|
||||||
@Override
|
@Override
|
||||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
|
|
||||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
||||||
final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance;
|
final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance;
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity {
|
||||||
final double vH = Math.sqrt( vX * vX + vZ * vZ );
|
final double vH = Math.sqrt( vX * vX + vZ * vZ );
|
||||||
spawnBaby( vX / vH * 0.8 + getDeltaMovement().x * 0.2, vZ / vH * 0.8 + getDeltaMovement().z * 0.2, null );
|
spawnBaby( vX / vH * 0.8 + getDeltaMovement().x * 0.2, vZ / vH * 0.8 + getDeltaMovement().z * 0.2, null );
|
||||||
spawnAnim();
|
spawnAnim();
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
super.performRangedAttack( target, damageMulti );
|
super.performRangedAttack( target, damageMulti );
|
||||||
|
@ -114,7 +114,7 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity {
|
||||||
groupData = spawnBaby( (random.nextDouble() - 0.5) * 0.3, (random.nextDouble() - 0.5) * 0.3, groupData );
|
groupData = spawnBaby( (random.nextDouble() - 0.5) * 0.3, (random.nextDouble() - 0.5) * 0.3, groupData );
|
||||||
}
|
}
|
||||||
spawnAnim();
|
spawnAnim();
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
}
|
}
|
||||||
super.remove( keepData );
|
super.remove( keepData );
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob
|
||||||
/** Called to attack the target with a ranged attack. */
|
/** Called to attack the target with a ranged attack. */
|
||||||
@Override
|
@Override
|
||||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
|
|
||||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
||||||
final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance;
|
final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance;
|
||||||
|
@ -176,6 +176,18 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -166,6 +166,18 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements IRange
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class SkeletonCreeperEntity extends _SpecialCreeperEntity {
|
||||||
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
|
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
|
||||||
bestiaryInfo.color( 0xC1C1C1 ).theme( BestiaryInfo.Theme.FOREST )
|
bestiaryInfo.color( 0xC1C1C1 ).theme( BestiaryInfo.Theme.FOREST )
|
||||||
.uniqueTextureBaseOnly()
|
.uniqueTextureBaseOnly()
|
||||||
.addExperience( 1 )
|
.addExperience( 1 ).undead()
|
||||||
.addToAttribute( Attributes.MAX_HEALTH, -4.0 )
|
.addToAttribute( Attributes.MAX_HEALTH, -4.0 )
|
||||||
.multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 );
|
.multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,6 +316,18 @@ public class _SpecialCreeperEntity extends CreeperEntity implements IExplodingMo
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -159,7 +159,7 @@ public class IcyEndermanEntity extends _SpecialEndermanEntity {
|
||||||
teleportTo( x, y, z );
|
teleportTo( x, y, z );
|
||||||
|
|
||||||
if( level.noCollision( this ) && !level.containsAnyLiquid( getBoundingBox() ) ) {
|
if( level.noCollision( this ) && !level.containsAnyLiquid( getBoundingBox() ) ) {
|
||||||
if( spawnParticles ) level.broadcastEntityEvent( this, References.EVENT_TELEPORT_TRAIL_PARTICLES );
|
if( spawnParticles ) References.EntityEvent.TELEPORT_TRAIL_PARTICLES.broadcast( this );
|
||||||
getNavigation().stop();
|
getNavigation().stop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,18 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class CorporealShiftGhastEntity extends _SpecialGhastEntity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_GHAST_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.GHAST_SHOOT.play( this );
|
||||||
|
|
||||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
||||||
final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() );
|
final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() );
|
||||||
|
|
|
@ -92,7 +92,7 @@ public class QueenGhastEntity extends _SpecialGhastEntity {
|
||||||
final double vH = Math.sqrt( vX * vX + vZ * vZ );
|
final double vH = Math.sqrt( vX * vX + vZ * vZ );
|
||||||
spawnBaby( vX / vH + getDeltaMovement().x * 0.2, vZ / vH + getDeltaMovement().z * 0.2, null );
|
spawnBaby( vX / vH + getDeltaMovement().x * 0.2, vZ / vH + getDeltaMovement().z * 0.2, null );
|
||||||
spawnAnim();
|
spawnAnim();
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_GHAST_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.GHAST_SHOOT.play( this );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
super.performRangedAttack( target, damageMulti );
|
super.performRangedAttack( target, damageMulti );
|
||||||
|
@ -114,7 +114,7 @@ public class QueenGhastEntity extends _SpecialGhastEntity {
|
||||||
groupData = spawnBaby( (random.nextDouble() - 0.5) * 0.3, (random.nextDouble() - 0.5) * 0.3, groupData );
|
groupData = spawnBaby( (random.nextDouble() - 0.5) * 0.3, (random.nextDouble() - 0.5) * 0.3, groupData );
|
||||||
}
|
}
|
||||||
spawnAnim();
|
spawnAnim();
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
}
|
}
|
||||||
super.remove( keepData );
|
super.remove( keepData );
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob
|
||||||
/** Called to attack the target with a ranged attack. */
|
/** Called to attack the target with a ranged attack. */
|
||||||
@Override
|
@Override
|
||||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_GHAST_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.GHAST_SHOOT.play( this );
|
||||||
|
|
||||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
||||||
final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() );
|
final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() );
|
||||||
|
@ -200,6 +200,18 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -163,6 +163,18 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial
|
||||||
xpReward = getSize() + xp;
|
xpReward = getSize() + xp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -171,6 +171,18 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements IRange
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class SpitfireSkeletonEntity extends _SpecialSkeletonEntity {
|
||||||
/** Called to attack the target with a ranged attack. */
|
/** Called to attack the target with a ranged attack. */
|
||||||
@Override
|
@Override
|
||||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
|
|
||||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,18 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -170,6 +170,18 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe
|
||||||
xpReward = getSize() + xp;
|
xpReward = getSize() + xp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -166,6 +166,18 @@ public class _SpecialSpiderEntity extends SpiderEntity implements IRangedAttackM
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -223,7 +223,7 @@ public class WindWitchEntity extends _SpecialWitchEntity {
|
||||||
teleportTo( x, y, z );
|
teleportTo( x, y, z );
|
||||||
|
|
||||||
if( level.noCollision( this ) && !level.containsAnyLiquid( getBoundingBox() ) ) {
|
if( level.noCollision( this ) && !level.containsAnyLiquid( getBoundingBox() ) ) {
|
||||||
if( spawnParticles ) level.broadcastEntityEvent( this, References.EVENT_TELEPORT_TRAIL_PARTICLES );
|
if( spawnParticles ) References.EntityEvent.TELEPORT_TRAIL_PARTICLES.broadcast( this );
|
||||||
getNavigation().stop();
|
getNavigation().stop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,6 +391,18 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class SpitfireWitherSkeletonEntity extends _SpecialWitherSkeletonEntity {
|
||||||
/** Called to attack the target with a ranged attack. */
|
/** Called to attack the target with a ranged attack. */
|
||||||
@Override
|
@Override
|
||||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||||
if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 );
|
References.LevelEvent.BLAZE_SHOOT.play( this );
|
||||||
|
|
||||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread();
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,18 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,6 +3,8 @@ package fathertoast.specialmobs.common.entity.zombie;
|
||||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||||
|
import fathertoast.specialmobs.common.config.species.HuskZombieSpeciesConfig;
|
||||||
|
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
|
||||||
import fathertoast.specialmobs.common.entity.MobHelper;
|
import fathertoast.specialmobs.common.entity.MobHelper;
|
||||||
import fathertoast.specialmobs.common.util.References;
|
import fathertoast.specialmobs.common.util.References;
|
||||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||||
|
@ -18,6 +20,8 @@ import net.minecraft.util.SoundEvent;
|
||||||
import net.minecraft.util.SoundEvents;
|
import net.minecraft.util.SoundEvents;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
@SpecialMob
|
@SpecialMob
|
||||||
public class HuskZombieEntity extends _SpecialZombieEntity {
|
public class HuskZombieEntity extends _SpecialZombieEntity {
|
||||||
|
|
||||||
|
@ -34,6 +38,15 @@ public class HuskZombieEntity extends _SpecialZombieEntity {
|
||||||
.addExperience( 1 );
|
.addExperience( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SpecialMob.ConfigSupplier
|
||||||
|
public static SpeciesConfig createConfig( MobFamily.Species<?> species ) {
|
||||||
|
return new HuskZombieSpeciesConfig( species, DEFAULT_BOW_CHANCE, DEFAULT_SHIELD_CHANCE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return This entity's species config. */
|
||||||
|
@Override
|
||||||
|
public HuskZombieSpeciesConfig getConfig() { return (HuskZombieSpeciesConfig) getSpecies().config; }
|
||||||
|
|
||||||
@SpecialMob.AttributeSupplier
|
@SpecialMob.AttributeSupplier
|
||||||
public static AttributeModifierMap.MutableAttribute createAttributes() { return HuskEntity.createAttributes(); }
|
public static AttributeModifierMap.MutableAttribute createAttributes() { return HuskEntity.createAttributes(); }
|
||||||
|
|
||||||
|
@ -73,6 +86,22 @@ public class HuskZombieEntity extends _SpecialZombieEntity {
|
||||||
return MobHelper.tipArrow( arrow, Effects.HUNGER );
|
return MobHelper.tipArrow( arrow, Effects.HUNGER );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true if the species is not a husk and not damaged by water. */
|
||||||
|
private static final Function<MobFamily.Species<?>, Boolean> HUSK_CONVERSION_SELECTOR =
|
||||||
|
( species ) -> species != SPECIES && !species.config.GENERAL.isDamagedByWater.get();
|
||||||
|
|
||||||
|
/** Performs this zombie's drowning conversion. */
|
||||||
|
@Override
|
||||||
|
protected void doUnderWaterConversion() {
|
||||||
|
// Select a random non-husk, non-water-sensitive zombie; defaults to a normal zombie
|
||||||
|
convertToZombieType(
|
||||||
|
getConfig().HUSK.convertVariantChance.rollChance( random, level, blockPosition() ) ?
|
||||||
|
MobFamily.ZOMBIE.nextVariant( level, blockPosition(), HUSK_CONVERSION_SELECTOR, _SpecialZombieEntity.SPECIES ).entityType.get() :
|
||||||
|
_SpecialZombieEntity.SPECIES.entityType.get()
|
||||||
|
);
|
||||||
|
References.LevelEvent.HUSK_CONVERTED_TO_ZOMBIE.play( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------- Husk Implementations ----------------
|
//--------------- Husk Implementations ----------------
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final double DEFAULT_BOW_CHANCE = 0.05;
|
protected static final double DEFAULT_BOW_CHANCE = 0.05;
|
||||||
protected static final double DEFAULT_SHIELD_CHANCE = 0.05;
|
protected static final double DEFAULT_SHIELD_CHANCE = 0.02;
|
||||||
|
|
||||||
@SpecialMob.ConfigSupplier
|
@SpecialMob.ConfigSupplier
|
||||||
public static SpeciesConfig createConfig( MobFamily.Species<?> species ) {
|
public static SpeciesConfig createConfig( MobFamily.Species<?> species ) {
|
||||||
|
@ -207,6 +207,19 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return True if this zombie can convert in water. */
|
||||||
|
@Override
|
||||||
|
protected boolean convertsInWater() { return !isSensitiveToWater(); }
|
||||||
|
|
||||||
|
// TODO Drowned transform
|
||||||
|
// /** Performs this zombie's drowning conversion. */
|
||||||
|
// @Override
|
||||||
|
// protected void doUnderWaterConversion() {
|
||||||
|
// // Select a random drowned
|
||||||
|
// convertToZombieType( MobFamily.DROWNED.nextVariant( level, blockPosition() ).entityType.get() );
|
||||||
|
// References.LevelEvent.ZOMBIE_CONVERTED_TO_DROWNED.play( this );
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
//--------------- ISpecialMob Implementation ----------------
|
//--------------- ISpecialMob Implementation ----------------
|
||||||
|
|
||||||
|
@ -229,6 +242,18 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -227,6 +227,18 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme
|
||||||
@Override
|
@Override
|
||||||
public final void setExperience( int xp ) { xpReward = xp; }
|
public final void setExperience( int xp ) { xpReward = xp; }
|
||||||
|
|
||||||
|
/** Converts this entity to one of another type. */
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends MobEntity> T convertTo( EntityType<T> entityType, boolean keepEquipment ) {
|
||||||
|
final T replacement = super.convertTo( entityType, keepEquipment );
|
||||||
|
if( replacement instanceof ISpecialMob && level instanceof IServerWorld ) {
|
||||||
|
MobHelper.finalizeSpawn( replacement, (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||||
|
SpawnReason.CONVERSION, null );
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,13 +2,18 @@ package fathertoast.specialmobs.common.util;
|
||||||
|
|
||||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.nbt.ListNBT;
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.nbt.StringNBT;
|
import net.minecraft.nbt.StringNBT;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public final class References {
|
public final class References {
|
||||||
|
@ -93,7 +98,7 @@ public final class References {
|
||||||
|
|
||||||
/** Bit flags that can be provided to {@link net.minecraft.world.World#setBlock(BlockPos, BlockState, int)}. */
|
/** Bit flags that can be provided to {@link net.minecraft.world.World#setBlock(BlockPos, BlockState, int)}. */
|
||||||
@SuppressWarnings( "unused" )
|
@SuppressWarnings( "unused" )
|
||||||
public static class SetBlockFlags {
|
public static final class SetBlockFlags {
|
||||||
/** Triggers a block update. */
|
/** Triggers a block update. */
|
||||||
public static final int BLOCK_UPDATE = 0b0000_0001;
|
public static final int BLOCK_UPDATE = 0b0000_0001;
|
||||||
/** On servers, sends the change to clients. On clients, triggers a render update. */
|
/** On servers, sends the change to clients. On clients, triggers a render update. */
|
||||||
|
@ -115,13 +120,77 @@ public final class References {
|
||||||
public static final int DEFAULTS = BLOCK_UPDATE | UPDATE_CLIENT;
|
public static final int DEFAULTS = BLOCK_UPDATE | UPDATE_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entity events; used in World#broadcastEntityEvent(Entity, byte) then executed by Entity#handleEntityEvent(byte)
|
/**
|
||||||
public static final byte EVENT_TELEPORT_TRAIL_PARTICLES = 46;
|
* Entity events. Sent from the server, executed on the client via {@link Entity#handleEntityEvent(byte)}.
|
||||||
|
* This only contains event codes for Entity and LivingEntity.
|
||||||
|
*/
|
||||||
|
public enum EntityEvent {
|
||||||
|
// Note: if we want to go deeper, it may be wise to make this generic to only allow an appropriate Entity subclass.
|
||||||
|
// There's no need to go to MobEntity as its sole event is already nicely abstracted.
|
||||||
|
|
||||||
// Level events; used in World#levelEvent(PlayerEntity, int, BlockPos, int) then executed by WorldRenderer#levelEvent(PlayerEntity, int, BlockPos, int)
|
HURT_SOUND( 2 ), HURT_SOUND_THORNS( 33 ), HURT_SOUND_DROWN( 36 ),
|
||||||
public static final int EVENT_GHAST_WARN = 1015;
|
HURT_SOUND_BURNING( 37 ), HURT_SOUND_SWEET_BERRY_BUSH( 44 ),
|
||||||
public static final int EVENT_GHAST_SHOOT = 1016;
|
DEATH_SOUND( 3 ),
|
||||||
public static final int EVENT_BLAZE_SHOOT = 1018;
|
SHIELD_BLOCK_SOUND( 29 ), SHIELD_BREAK_SOUND( 30 ),
|
||||||
|
TELEPORT_TRAIL_PARTICLES( 46 ),
|
||||||
|
ITEM_BREAK_FX_MAIN_HAND( 47 ), ITEM_BREAK_FX_OFF_HAND( 48 ),
|
||||||
|
ITEM_BREAK_FX_HEAD( 49 ), ITEM_BREAK_FX_CHEST( 50 ), ITEM_BREAK_FX_LEGS( 51 ), ITEM_BREAK_FX_FEET( 52 ),
|
||||||
|
HONEY_SLIDE_PARTICLES( 53 ) /* This is the only event from Entity. */, HONEY_JUMP_PARTICLES( 54 ),
|
||||||
|
SWAP_HAND_ITEMS( 55 );
|
||||||
|
|
||||||
|
private final byte ID;
|
||||||
|
|
||||||
|
EntityEvent( int id ) { ID = (byte) id; }
|
||||||
|
|
||||||
|
/** Sends this event from the given server entity to its client-sided counterpart. */
|
||||||
|
public void broadcast( LivingEntity entity ) { entity.level.broadcastEntityEvent( entity, ID ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple level events (ones that do not use extra metadata). Sent from the server, then executed on the client
|
||||||
|
* via {@link net.minecraft.client.renderer.WorldRenderer#levelEvent(PlayerEntity, int, BlockPos, int)}.
|
||||||
|
*/
|
||||||
|
public enum LevelEvent {
|
||||||
|
// Note: if metadata events are needed, they will need to be implemented in a separate class
|
||||||
|
|
||||||
|
DISPENSER_DISPENSE( 1000 ), DISPENSER_FAIL( 1001 ), DISPENSER_LAUNCH( 1002 ),
|
||||||
|
ENDER_EYE_LAUNCH( 1003 ), ENDER_EYE( 2003 ), END_PORTAL_FRAME_FILL( 1503 ),
|
||||||
|
FIREWORK_ROCKET_SHOOT( 1004 ),
|
||||||
|
IRON_DOOR_OPEN( 1005 ), WOODEN_DOOR_OPEN( 1006 ), WOODEN_TRAPDOOR_OPEN( 1007 ), FENCE_GATE_OPEN( 1008 ),
|
||||||
|
IRON_DOOR_CLOSE( 1011 ), WOODEN_DOOR_CLOSE( 1012 ), WOODEN_TRAPDOOR_CLOSE( 1013 ), FENCE_GATE_CLOSE( 1014 ),
|
||||||
|
IRON_TRAPDOOR_CLOSE( 1036 ), IRON_TRAPDOOR_OPEN( 1037 ),
|
||||||
|
FIRE_EXTINGUISH( 1009 ), LAVA_EXTINGUISH( 1501 ), REDSTONE_TORCH_BURNOUT( 1502 ),
|
||||||
|
GHAST_WARN( 1015 ), GHAST_SHOOT( 1016 ),
|
||||||
|
ENDER_DRAGON_SHOOT( 1017 ), ENDER_DRAGON_GROWL( 3001 ),
|
||||||
|
BLAZE_SHOOT( 1018 ),
|
||||||
|
ZOMBIE_ATTACK_WOODEN_DOOR( 1019 ), ZOMBIE_ATTACK_IRON_DOOR( 1020 ), ZOMBIE_BREAK_WOODEN_DOOR( 1021 ),
|
||||||
|
ZOMBIE_INFECT( 1026 ), ZOMBIE_VILLAGER_CONVERTED( 1027 ),
|
||||||
|
ZOMBIE_CONVERTED_TO_DROWNED( 1040 ), HUSK_CONVERTED_TO_ZOMBIE( 1041 ),
|
||||||
|
WITHER_BREAK_BLOCK( 1022 ), WITHER_SHOOT( 1024 ),
|
||||||
|
BAT_TAKEOFF( 1025 ),
|
||||||
|
ANVIL_DESTROY( 1029 ), ANVIL_USE( 1030 ), ANVIL_LAND( 1031 ),
|
||||||
|
BREWING_STAND_BREW( 1035 ), GRINDSTONE_USE( 1042 ), BOOK_PAGE_TURN( 1043 ), SMITHING_TABLE_USE( 1044 ),
|
||||||
|
PORTAL_TRAVEL( 1032 ),
|
||||||
|
CHORUS_FLOWER_GROW( 1033 ), CHORUS_FLOWER_DEATH( 1034 ),
|
||||||
|
PHANTOM_BITE( 1039 ),
|
||||||
|
SMOKE_AND_FLAME( 2004 ),
|
||||||
|
EXPLOSION_PARTICLE( 2008 ), CLOUD_PARTICLES( 2009 ), EXPLOSION_EMITTER( 3000 );
|
||||||
|
|
||||||
|
private final int ID;
|
||||||
|
|
||||||
|
LevelEvent( int id ) { ID = id; }
|
||||||
|
|
||||||
|
/** Plays this event at the entity's position, if the entity is not silenced. */
|
||||||
|
public void play( Entity entity ) {
|
||||||
|
if( !entity.isSilent() ) play( entity.level, entity.blockPosition() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Plays this event at a particular position. */
|
||||||
|
public void play( World world, BlockPos pos ) { play( world, null, pos ); }
|
||||||
|
|
||||||
|
/** Plays this event at a particular position, excluding a particular player. */
|
||||||
|
public void play( World world, @Nullable PlayerEntity player, BlockPos pos ) { world.levelEvent( player, ID, pos, 0 ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------- NBT STUFF ----------------
|
//--------------- NBT STUFF ----------------
|
||||||
|
|
Loading…
Add table
Reference in a new issue