Skip to content

Instantly share code, notes, and snippets.

@Densamisten
Forked from Ensamisten/FireworkCommand.java
Last active March 17, 2024 20:23
Show Gist options
  • Save Densamisten/dd6f20133499db76ef8b7b0cee01f3be to your computer and use it in GitHub Desktop.
Save Densamisten/dd6f20133499db76ef8b7b0cee01f3be to your computer and use it in GitHub Desktop.
FireworkCommand. (Tested for Forge in Minecraft: 1,18-1.20.4). The mixin allows for firework to pass through blocks sometimes. Usage: /firework
package io.github.ensamisten.fireworkmod;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.context.CommandContext;
import io.github.ensamisten.forgient.mixin.FireworkRocketEntityMixin;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
import static net.minecraft.world.item.Items.FIREWORK_ROCKET;
/**
* Firework command for Firework Mod
* License: Free for all use.
**/
public class FireworkCommand {
public FireworkCommand(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("firework")
.then(Commands.argument("pos", BlockPosArgument.blockPos())
.executes(context -> execute(context, BlockPosArgument.getLoadedBlockPos(context, "pos"), 1, 0xFFFFFF, 1,1))
.then(Commands.argument("count", IntegerArgumentType.integer(1))
.then(Commands.argument("shape", IntegerArgumentType.integer(0, 2))
.then(Commands.argument("colors", IntegerArgumentType.integer(0, 16777215))
.then(Commands.argument("flight", IntegerArgumentType.integer(1, 3))
.executes(context -> execute(context, BlockPosArgument.getLoadedBlockPos(context, "pos"), IntegerArgumentType.getInteger(context, "count"), IntegerArgumentType.getInteger(context, "shape"), IntegerArgumentType.getInteger(context, "colors"), IntegerArgumentType.getInteger(context, "flight")))
)
)
)
)
)
.then(Commands.literal("entity")
.then(Commands.argument("targets", EntityArgument.entities())
.then(Commands.argument("count", IntegerArgumentType.integer(1))
.then(Commands.argument("shape", IntegerArgumentType.integer(0, 2))
.then(Commands.argument("colors", IntegerArgumentType.integer(0, 16777215))
.then(Commands.argument("flight", IntegerArgumentType.integer(1, 3))
.executes(context -> executeFromEntities(context, EntityArgument.getEntities(context, "targets"), IntegerArgumentType.getInteger(context, "count"), IntegerArgumentType.getInteger(context, "shape"), IntegerArgumentType.getInteger(context, "colors"), IntegerArgumentType.getInteger(context, "flight")))
)
)
)
)
)
)
);
}
private static int execute(CommandContext<CommandSourceStack> context, BlockPos pos, int count, int shape, int colors, int flight) {
Level level = context.getSource().getLevel();
for (int i = 0; i < count; i++) {
double offsetX = (new Random().nextDouble() - 0.5) * 5.0;
double offsetY = (new Random().nextDouble() - 0.5) * 5.0;
double offsetZ = (new Random().nextDouble() - 0.5) * 5.0;
ItemStack fireworkStar = createFireworkStar(shape, colors, flight);
// Create a new instance of FireworkRocketEntity
FireworkRocketEntity firework = new FireworkRocketEntity(level, pos.getX() + 0.5 + offsetX, pos.getY() + 0.5 + offsetY, pos.getZ() + 0.5 + offsetZ, fireworkStar);
// Apply mixin logic here if needed
firework.setDeltaMovement(firework.getDeltaMovement().add(0.0D, 0.05D, 0.0D));
level.addFreshEntity(firework);
}
return Command.SINGLE_SUCCESS;
}
private static int executeFromEntities(CommandContext<CommandSourceStack> context, Iterable<? extends Entity> targets, int count, int shape, int colors, int flight) {
Level level = context.getSource().getLevel();
for (Entity target : targets) {
for (int i = 0; i < count; i++) {
double offsetX = (new Random().nextDouble() - 0.5) * 5.0;
double offsetY = (new Random().nextDouble() - 0.5) * 5.0;
double offsetZ = (new Random().nextDouble() - 0.5) * 5.0;
ItemStack fireworkStar = createFireworkStar(shape, colors, flight);
FireworkRocketEntity firework = new FireworkRocketEntity(level, target.getX() + 0.5 + offsetX, target.getY() + target.getBbHeight() + 0.5 + offsetY, target.getZ() + 0.5 + offsetZ, fireworkStar);
level.addFreshEntity(firework);
}
}
return Command.SINGLE_SUCCESS;
}
private static ItemStack createFireworkStar(int shape, int colors, int flight) {
ItemStack fireworkStar = new ItemStack(Items.FIREWORK_ROCKET.asItem());
CompoundTag fireworksNBT = new CompoundTag();
ListTag explosionsList = new ListTag();
CompoundTag explosionTag = getCompoundTag(shape);
explosionTag.putIntArray("Colors", new int[]{colors}); // Set the desired color
explosionTag.putIntArray("FadeColors", new int[]{0xFFFFFF}); // White fade color
explosionsList.add(explosionTag);
fireworksNBT.put("Explosions", explosionsList);
fireworkStar.addTagElement("Fireworks", fireworksNBT);
// Set the flight duration
CompoundTag fireworkItemNBT = fireworkStar.getOrCreateTagElement("Fireworks");
fireworkItemNBT.putInt("Flight", flight);
return fireworkStar;
}
@NotNull
private static CompoundTag getCompoundTag(int shape) {
CompoundTag explosionTag = new CompoundTag();
switch (shape) {
// Small ball explosion
case 1 -> explosionTag.putInt("Type", 1); // Large ball explosion
case 2 -> explosionTag.putInt("Type", 2); // Star-shaped explosion
// Add more shapes as needed
default -> explosionTag.putInt("Type", 0); // Default to small ball explosion
}
explosionTag.putBoolean("Flicker", true); // Flickering effect
explosionTag.putBoolean("Trail", true); // Trail effect
return explosionTag;
}
}
package io.github.ensamisten.fireworkmod;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
/**
* Firework command registry for Firework Mod
* License: Free for all use.
**/
@Mod.EventBusSubscriber(modid = Firework.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class FreworkCommandRegistry {
/**
* Register FireworkCommand
* License: Free for all use.
**/
@SubscribeEvent
public static void registerCommandsEvent(RegisterCommandsEvent event) {
new FireworkCommand(event.getDispatcher());
}
}
package io.github.ensamisten.fireworkmod.mixin;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.HitResult;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.Vec3;
/**
* Firework rocket entity mixin for Firework Mod
* License: Free for all use.
**/
@Mixin(FireworkRocketEntity.class)
public abstract class FireworkRocketEntityMixin extends Entity {
protected FireworkRocketEntityMixin(EntityType<?> entityType, Level level) {
super(entityType, level);
}
@Inject(method = "tick", at = @At("HEAD"), cancellable = true)
private void allowPassingThroughBlocks(CallbackInfo ci) {
// Get the rocket's current position and motion
Vec3 currentPosition = this.position();
Vec3 motion = this.getDeltaMovement();
// Calculate the next position after applying the motion
Vec3 nextPosition = currentPosition.add(motion);
// Check if the rocket's movement would result in a collision with a block
HitResult hitResult = this.level.clip(new ClipContext(currentPosition, nextPosition, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this));
// If the rocket is colliding with a block, cancel the collision and move the rocket
if (hitResult.getType() != HitResult.Type.MISS) {
ci.cancel();
this.setPos(nextPosition.x, nextPosition.y, nextPosition.z);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment