public class TealMeteorEntity extends FallingBlockEntity {
@Override
public void tick() {
super.tick();
// Smoke trail
level().addParticle(
ParticleTypes.SOUL_FIRE_FLAME,
getX(),
getY(),
getZ(),
0,
-0.1,
0
);
// Impact
if (this.onGround()) {
BlockPos center = this.blockPosition();
// Small explosion (doesn't destroy everything)
level().explode(
this,
center.getX(),
center.getY(),
center.getZ(),
4.0F,
Level.ExplosionInteraction.NONE
);
// Create infection crater
createCrystalCrater(center);
discard();
}
}
}
private void createCrystalCrater(BlockPos center) {
int radius = 8;
for (int x = -radius; x <= radius; x++) {
for (int y = -3; y <= 2; y++) {
for (int z = -radius; z <= radius; z++) {
BlockPos pos = center.offset(x, y, z);
double distance = Math.sqrt(x*x + y*y + z*z);
if(distance <= radius) {
if(level().getRandom().nextFloat() < 0.7F){
level().setBlock(
pos,
ModBlocks.TEAL_CRYSTAL_BLOCK.get().defaultBlockState(),
3
);
}
}
}
}
}
}
AABB area = new AABB(center).inflate(20);
for(LivingEntity entity :
level().getEntitiesOfClass(LivingEntity.class, area)){
entity.addEffect(new MobEffectInstance(
ModEffects.TEAL_INFECTION.get(),
1200,
0
));
}
@SubscribeEvent
public static void worldTick(LevelTickEvent.Post event){
Level level = event.getLevel();
if(level.getRandom().nextInt(24000) == 0){
BlockPos spawn = new BlockPos(
level.getRandom().nextInt(5000) - 2500,
250,
level.getRandom().nextInt(5000) - 2500
);
TealMeteorEntity meteor =
new TealMeteorEntity(level);
meteor.setPos(
spawn.getX(),
spawn.getY(),
spawn.getZ()
);
level.addFreshEntity(meteor);
}
}
public class MeteorManager {
// Total meteors that will ever fall
public static final int MAX_METEORS =
5 + new Random().nextInt(6); // 5-10
public static int meteorsSpawned = 0;
public static boolean canSpawnMeteor() {
return meteorsSpawned < MAX_METEORS;
}
public static void meteorSpawned() {
meteorsSpawned++;
}
}
@SubscribeEvent
public static void onWorldTick(LevelTickEvent.Post event) {
Level level = event.getLevel();
// Stop if we've reached the limit
if (!MeteorManager.canSpawnMeteor()) {
return;
}
// Random chance every tick
if (level.getRandom().nextInt(24000) == 0) {
BlockPos spawnPos = new BlockPos(
level.getRandom().nextInt(5000) - 2500,
250,
level.getRandom().nextInt(5000) - 2500
);
TealMeteorEntity meteor = new TealMeteorEntity(level);
meteor.setPos(spawnPos.getX(), spawnPos.getY(), spawnPos.getZ());
level.addFreshEntity(meteor);
MeteorManager.meteorSpawned();
System.out.println(
"Meteor " +
MeteorManager.meteorsSpawned +
" of " +
MeteorManager.MAX_METEORS
);
}
}
if (MeteorManager.meteorsSpawned >= MeteorManager.MAX_METEORS) {
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
player.sendSystemMessage(Component.literal(
"§bThe final Teal Crystal Meteor has fallen. The infection has begun..."
));
}
// Start global infection phase here.
}
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
player.sendSystemMessage(Component.literal(
"§3A Teal Crystal Meteor has crashed! (" +
MeteorManager.meteorsSpawned +
"/" +
MeteorManager.MAX_METEORS +
")"
));
}