Initial project setup for ElytraMace mod

Add Gradle build files, MIT license, and .gitignore. Implement ElytraMace client mod with keybindings for target selection and attack, including mixin for entity glowing effect. Register mod metadata and mixins configuration for Fabric loader.
This commit is contained in:
2026-01-05 04:30:36 +01:00
commit 45eb6e081b
13 changed files with 698 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
package com.kasetoatz.elytramace;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.projectile.ProjectileUtil;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.glfw.GLFW;
public class ElytraMace implements ClientModInitializer
{
private MinecraftClient client;
private final KeyBinding.Category keybindCategory = KeyBinding.Category.create(Identifier.of("elytramace", "elytramace"));
private final KeyBinding selectTargetKeybind = KeyBindingHelper.registerKeyBinding(
new KeyBinding(
"key.elytramace.select_target",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_KP_8,
keybindCategory
)
);
private final KeyBinding attackKeybind = KeyBindingHelper.registerKeyBinding(
new KeyBinding(
"key.elytramace.attack",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_KP_7,
keybindCategory
)
);
private KeyBinding cancelFlightKeybind;
public static LivingEntity TARGET;
private boolean isAttacking = false;
private LivingEntity getTarget()
{
Entity camera = client.getCameraEntity();
if (camera == null)
{
return null;
}
HitResult hitResult = camera.raycast(client.options.getSimulationDistance().getValue() * 16, 0F, false);
Vec3d start = camera.getCameraPosVec(0F);
double squaredDist = hitResult.getPos().squaredDistanceTo(start);
double newDist = Math.sqrt(squaredDist);
Vec3d rotation = camera.getRotationVec(0F);
Vec3d end = start.add(rotation.multiply(newDist));
Box box = camera.getBoundingBox().stretch(rotation.multiply(newDist)).expand(1D);
EntityHitResult result = ProjectileUtil.raycast(camera, start, end, box, EntityPredicates.CAN_HIT, squaredDist);
if (result == null || !(result.getEntity() instanceof LivingEntity))
{
return null;
}
return (LivingEntity)result.getEntity();
}
private void getCancelFlightKeybind()
{
for (KeyBinding keybind : client.options.allKeys)
{
if (keybind.getBoundKeyTranslationKey().equals("key.elytracancel.cancel_flight"))
{
cancelFlightKeybind = keybind;
}
}
}
private void updateTarget()
{
LivingEntity nextTarget = getTarget();
if (nextTarget == TARGET)
{
TARGET = null;
}
else if (nextTarget != null)
{
TARGET = nextTarget;
}
}
private int getItemIndex(PlayerInventory inventory, Item item)
{
for (int i = 0; i < 9; i++)
{
if (inventory.getStack(i).isOf(item))
{
return i;
}
}
return -1;
}
private void attack()
{
if (client.player == null || client.interactionManager == null)
{
return;
}
isAttacking = true;
PlayerInventory inventory = client.player.getInventory();
ClientPlayerInteractionManager manager = client.interactionManager;
int fireworkSlot = getItemIndex(inventory, Items.FIREWORK_ROCKET);
int maceSlot = getItemIndex(inventory, Items.MACE);
if (fireworkSlot == -1 || maceSlot == -1)
{
return;
}
inventory.setSelectedSlot(fireworkSlot);
manager.interactItem(client.player, Hand.MAIN_HAND);
isAttacking = false;
}
@Override
public void onInitializeClient()
{
client = MinecraftClient.getInstance();
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (cancelFlightKeybind == null && client.options != null)
{
getCancelFlightKeybind();
}
while (selectTargetKeybind.wasPressed() && !isAttacking)
{
updateTarget();
}
while (attackKeybind.wasPressed() && TARGET != null && !isAttacking)
{
attack();
}
});
}
}