Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/client/java/com/example/ExampleModClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
import net.minecraft.client.render.entity.FlyingItemEntityRenderer;

import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
import net.minecraft.client.render.entity.EmptyEntityRenderer;
public class ExampleModClient implements ClientModInitializer {

@Override
Expand All @@ -19,6 +20,12 @@ public void onInitializeClient() {
EntityRendererRegistry.register(ModEntities.GOD_BOSS, GodBossEntityRenderer::new);


EntityRendererRegistry.register(ModEntities.GOD_BOSS, GodBossEntityRenderer::new);


EntityRendererRegistry.register(ModEntities.DEVASTATION_DOME_ENTITY, EmptyEntityRenderer::new);




System.out.println("GodMod client initialized with entity renderers and custom boss model");
Expand Down
200 changes: 200 additions & 0 deletions src/main/java/com/example/DevastationDomeEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package com.example;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.damage.DamageTypes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.world.World;

import java.util.List;

public class DevastationDomeEntity extends Entity {
private static final int DOME_RADIUS = 15;
private static final int DOME_DURATION_TICKS = 200;
private static final float DAMAGE_PER_TICK = 100000.0F;
private static final int DAMAGE_INTERVAL = 1;

private int lifeTicks = 0;
private BlockPos domeCenter;

public DevastationDomeEntity(EntityType<?> type, World world) {
super(type, world);
this.noClip = true;
this.setInvulnerable(true);
}

public DevastationDomeEntity(EntityType<?> type, World world, BlockPos center) {
this(type, world);
this.domeCenter = center;
this.setPosition(center.getX() + 0.5, center.getY() + 0.5, center.getZ() + 0.5);
}

@Override
protected void initDataTracker(net.minecraft.entity.data.DataTracker.Builder builder) {
// No data to track
}

@Override
public void tick() {
super.tick();

if (!this.getWorld().isClient) {
lifeTicks++;

// Apply damage every tick
if (lifeTicks % DAMAGE_INTERVAL == 0) {
applyDomeDamage();
}

// Spawn particles every 5 ticks
if (lifeTicks % 5 == 0) {
spawnDomeParticles();
}

// Remove after duration
if (lifeTicks >= DOME_DURATION_TICKS) {
removeDome();
this.discard();
}
}
}

private void applyDomeDamage() {
if (!(this.getWorld() instanceof ServerWorld serverWorld)) {
return;
}

if (domeCenter == null) {
domeCenter = this.getBlockPos();
}

// Create damage box
Box damageBox = new Box(domeCenter).expand(DOME_RADIUS);

// Find all living entities except players
List<LivingEntity> entities = this.getWorld().getEntitiesByClass(
LivingEntity.class,
damageBox,
entity -> {
double distance = entity.getPos().distanceTo(domeCenter.toCenterPos());
return distance <= DOME_RADIUS && !(entity instanceof PlayerEntity);
}
);

// Create damage source using the server world's damage sources
DamageSource lethalDamage = serverWorld.getDamageSources().outOfWorld();

// Apply damage to all entities
for (LivingEntity entity : entities) {
entity.damage(serverWorld, lethalDamage, DAMAGE_PER_TICK);
}
}

private void spawnDomeParticles() {
if (!(this.getWorld() instanceof ServerWorld serverWorld)) {
return;
}

if (domeCenter == null) {
domeCenter = this.getBlockPos();
}

double spin = (lifeTicks % 360) * Math.PI / 180.0;

// Create dome shell particles
for (int yStep = 2; yStep <= DOME_RADIUS; yStep += 3) {
double height = yStep;
double radius = Math.sqrt(DOME_RADIUS * DOME_RADIUS - height * height);

for (int i = 0; i < 360; i += 24) {
double angle = Math.toRadians(i) + spin * 0.5;
double x = domeCenter.getX() + 0.5 + Math.cos(angle) * radius;
double z = domeCenter.getZ() + 0.5 + Math.sin(angle) * radius;
double y = domeCenter.getY() + height;

serverWorld.spawnParticles(
ParticleTypes.SOUL_FIRE_FLAME,
x, y, z, 1, 0.0, 0.0, 0.0, 0.01
);
serverWorld.spawnParticles(
ParticleTypes.DRAGON_BREATH,
x, y + 0.2, z, 1, 0.0, 0.0, 0.0, 0.0
);
}
}

// Create inner spiral
double progress = (double) lifeTicks / DOME_DURATION_TICKS;
int spiralPoints = (int) (30.0 + 50.0 * Math.sin(Math.min(progress, 1.0) * Math.PI));
double spiralRadius = 6.75;

for (int i = 0; i < spiralPoints; i++) {
double angle = spin + i * 0.35;
double x = domeCenter.getX() + 0.5 + Math.cos(angle) * spiralRadius * (0.9 + 0.1 * Math.sin(spin));
double z = domeCenter.getZ() + 0.5 + Math.sin(angle) * spiralRadius * (0.9 + 0.1 * Math.cos(spin));
double y = domeCenter.getY() + 4.5 + Math.sin(angle * 0.9) * 2.0;

serverWorld.spawnParticles(
ParticleTypes.ENCHANT,
x, y, z, 1, 0.0, 0.02, 0.0, 0.0
);
serverWorld.spawnParticles(
ParticleTypes.WARPED_SPORE,
x, y, z, 1, 0.0, 0.0, 0.0, 0.01
);
}
}

private void removeDome() {
if (!(this.getWorld() instanceof ServerWorld serverWorld)) {
return;
}

if (domeCenter == null) {
domeCenter = this.getBlockPos();
}

// Spawn explosion particle
serverWorld.spawnParticles(
ParticleTypes.EXPLOSION_EMITTER,
domeCenter.getX(), domeCenter.getY(), domeCenter.getZ(),
1, 0.0, 0.0, 0.0, 0.0
);
}

@Override
protected void readCustomDataFromNbt(NbtCompound nbt) {
lifeTicks = nbt.getInt("LifeTicks");

if (nbt.contains("DomeCenterX")) {
domeCenter = new BlockPos(
nbt.getInt("DomeCenterX"),
nbt.getInt("DomeCenterY"),
nbt.getInt("DomeCenterZ")
);
}
}

@Override
protected void writeCustomDataToNbt(NbtCompound nbt) {
nbt.putInt("LifeTicks", lifeTicks);

if (domeCenter != null) {
nbt.putInt("DomeCenterX", domeCenter.getX());
nbt.putInt("DomeCenterY", domeCenter.getY());
nbt.putInt("DomeCenterZ", domeCenter.getZ());
}
}

@Override
public boolean damage(ServerWorld world, DamageSource source, float amount) {
return false; // Invulnerable
}
}
166 changes: 166 additions & 0 deletions src/main/java/com/example/DevastationDomeScrollItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package com.example;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;

import java.util.List;

public class DevastationDomeScrollItem extends Item {
private static final int DOME_RADIUS = 15;
public static final SoundEvent DEVASTATION_SOUND = registerSound("destructive_dome_burst");

public DevastationDomeScrollItem(Settings settings) {
super(settings);
}

private static SoundEvent registerSound(String name) {
Identifier id = Identifier.of("godmod", name);
return Registry.register(Registries.SOUND_EVENT, id, SoundEvent.of(id));
}

@Override
public ActionResult use(World world, PlayerEntity user, Hand hand) {
ItemStack stack = user.getStackInHand(hand);

if (!world.isClient) {
ServerWorld serverWorld = (ServerWorld) world;
BlockPos centerPos = user.getBlockPos();

// Play sound (will be silent for now without sound file)
world.playSound(null, centerPos, DEVASTATION_SOUND, SoundCategory.PLAYERS, 2.0F, 1.0F);

// Spawn particle burst
spawnParticleBurst(serverWorld, centerPos);

// Spawn dome entity
DevastationDomeEntity domeEntity = new DevastationDomeEntity(
ModEntities.DEVASTATION_DOME_ENTITY,
serverWorld,
centerPos
);
serverWorld.spawnEntity(domeEntity);

// Send message to player
user.sendMessage(
Text.literal("Devastation Dome Activated!")
.formatted(Formatting.RED, Formatting.BOLD),
true
);

// Consume item if not in creative
if (!user.getAbilities().creativeMode) {
stack.decrement(1);
}
}

return ActionResult.SUCCESS;
}

private void spawnParticleBurst(ServerWorld world, BlockPos center) {
// Main explosion burst
for (int i = 0; i < 600; i++) {
double angle = Math.random() * Math.PI * 2.0;
double pitch = Math.random() * Math.PI;
double speed = 0.6 + Math.random();

double velX = Math.sin(pitch) * Math.cos(angle) * speed;
double velY = Math.cos(pitch) * speed;
double velZ = Math.sin(pitch) * Math.sin(angle) * speed;

world.spawnParticles(
ParticleTypes.FLAME,
center.getX() + 0.5, center.getY() + 0.5, center.getZ() + 0.5,
1, velX, velY, velZ, 0.08
);
world.spawnParticles(
ParticleTypes.SMOKE,
center.getX() + 0.5, center.getY() + 0.5, center.getZ() + 0.5,
1, velX, velY, velZ, 0.08
);
world.spawnParticles(
ParticleTypes.SOUL_FIRE_FLAME,
center.getX() + 0.5, center.getY() + 0.5, center.getZ() + 0.5,
1, velX * 0.6, velY * 0.6, velZ * 0.6, 0.02
);
world.spawnParticles(
ParticleTypes.WARPED_SPORE,
center.getX() + 0.5, center.getY() + 0.5, center.getZ() + 0.5,
1, velX * 0.4, velY * 0.4, velZ * 0.4, 0.01
);
}

// Ring particles
double innerRadius = 8.25;
double outerRadius = 12.75;

for (int i = 0; i < 360; i += 8) {
double radians = Math.toRadians(i);
double innerX = center.getX() + 0.5 + Math.cos(radians) * innerRadius;
double innerZ = center.getZ() + 0.5 + Math.sin(radians) * innerRadius;
double outerX = center.getX() + 0.5 + Math.cos(radians) * outerRadius;
double outerZ = center.getZ() + 0.5 + Math.sin(radians) * outerRadius;

world.spawnParticles(
ParticleTypes.ENCHANT,
innerX, center.getY() + 0.5, innerZ,
2, 0.0, 0.02, 0.0, 0.0
);
world.spawnParticles(
ParticleTypes.DRAGON_BREATH,
outerX, center.getY() + 1.0, outerZ,
1, 0.0, 0.02, 0.0, 0.0
);
}

// Vertical pillars
for (int i = 0; i < 15; i += 2) {
world.spawnParticles(
ParticleTypes.END_ROD,
center.getX() + 0.5 + innerRadius, center.getY() + i, center.getZ() + 0.5,
8, 0.02, 0.02, 0.02, 0.01
);
world.spawnParticles(
ParticleTypes.END_ROD,
center.getX() + 0.5 - innerRadius, center.getY() + i, center.getZ() + 0.5,
8, 0.02, 0.02, 0.02, 0.01
);
world.spawnParticles(
ParticleTypes.END_ROD,
center.getX() + 0.5, center.getY() + i, center.getZ() + 0.5 + innerRadius,
8, 0.02, 0.02, 0.02, 0.01
);
world.spawnParticles(
ParticleTypes.END_ROD,
center.getX() + 0.5, center.getY() + i, center.getZ() + 0.5 - innerRadius,
8, 0.02, 0.02, 0.02, 0.01
);
}
}

@Override
public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> tooltip, TooltipType type) {
tooltip.add(Text.translatable("item.godmod.devastation_dome_scroll.tooltip").formatted(Formatting.GRAY));
tooltip.add(Text.translatable("item.godmod.devastation_dome_scroll.tooltip2").formatted(Formatting.DARK_RED));
tooltip.add(Text.translatable("item.godmod.devastation_dome_scroll.tooltip3").formatted(Formatting.DARK_GRAY));
}

@Override
public boolean hasGlint(ItemStack stack) {
return true;
}
}
Loading