structure and player-dependent capes
This commit is contained in:
@@ -1,20 +1,24 @@
|
|||||||
package org.auraclient.auraclient;
|
package org.auraclient.auraclient;
|
||||||
|
|
||||||
import org.auraclient.auraclient.cloaks.Cloaks;
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import org.auraclient.auraclient.cloaks.Cloaks;
|
||||||
|
import org.auraclient.auraclient.event.KeyInputHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Massive thank you to IIpho3nix for making this mod, i (leo) have modified it to fit Aura Client
|
* Main class for the Aura Client mod.
|
||||||
*/
|
* Originally created by IIpho3nix and modified for Aura Client by leo.
|
||||||
|
*/
|
||||||
public class AuraClient implements ModInitializer {
|
public class AuraClient implements ModInitializer {
|
||||||
public static final String MOD_ID = "auraclient";
|
public static final String MOD_ID = "auraclient";
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
LOGGER.info("Initializing " + MOD_ID);
|
||||||
|
KeyInputHandler.register();
|
||||||
Cloaks.initialize();
|
Cloaks.initialize();
|
||||||
|
LOGGER.info(MOD_ID + " initialization complete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,25 +5,49 @@ import net.minecraft.client.gui.Drawable;
|
|||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a drawable texture in the Aura Client UI.
|
||||||
|
* Uses the builder pattern for flexible texture creation and configuration.
|
||||||
|
*/
|
||||||
public class AuraClientTexture implements Drawable {
|
public class AuraClientTexture implements Drawable {
|
||||||
// Textures
|
// Predefined textures
|
||||||
public static Identifier BOX_1_1 = Identifier.of("auraclient", "textures/gui/box_1_1.png");
|
public static final Identifier BOX_1_1 = Identifier.of("auraclient", "textures/gui/box_1_1.png");
|
||||||
|
|
||||||
Identifier sprite;
|
private final Identifier sprite;
|
||||||
int x = 0;
|
private int x;
|
||||||
int y = 0;
|
private int y;
|
||||||
int width = 0;
|
private int width;
|
||||||
int height = 0;
|
private int height;
|
||||||
boolean focused = false;
|
|
||||||
|
|
||||||
public AuraClientTexture(Identifier sprite) {
|
/**
|
||||||
|
* Creates a new texture with the specified sprite.
|
||||||
|
* @param sprite The identifier for the texture sprite
|
||||||
|
*/
|
||||||
|
private AuraClientTexture(Identifier sprite) {
|
||||||
this.sprite = sprite;
|
this.sprite = sprite;
|
||||||
|
this.x = 0;
|
||||||
|
this.y = 0;
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new builder instance for the texture.
|
||||||
|
* @param sprite The identifier for the texture sprite
|
||||||
|
* @return A new AuraClientTexture instance
|
||||||
|
*/
|
||||||
public static AuraClientTexture builder(Identifier sprite) {
|
public static AuraClientTexture builder(Identifier sprite) {
|
||||||
return new AuraClientTexture(sprite);
|
return new AuraClientTexture(sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the dimensions and position of the texture.
|
||||||
|
* @param x The x coordinate
|
||||||
|
* @param y The y coordinate
|
||||||
|
* @param width The width of the texture
|
||||||
|
* @param height The height of the texture
|
||||||
|
* @return This instance for method chaining
|
||||||
|
*/
|
||||||
public AuraClientTexture dimensions(int x, int y, int width, int height) {
|
public AuraClientTexture dimensions(int x, int y, int width, int height) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
@@ -32,6 +56,15 @@ public class AuraClientTexture implements Drawable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the focused state of the texture.
|
||||||
|
* @param focused The focused state
|
||||||
|
* @return This instance for method chaining
|
||||||
|
*/
|
||||||
|
public AuraClientTexture setFocused(boolean focused) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
context.drawTexture(RenderLayer::getGuiTextured, sprite, x, y, 0, 0, width, height, width, height);
|
context.drawTexture(RenderLayer::getGuiTextured, sprite, x, y, 0, 0, width, height, width, height);
|
||||||
|
|||||||
@@ -1,118 +1,154 @@
|
|||||||
package org.auraclient.auraclient.cloaks;
|
package org.auraclient.auraclient.cloaks;
|
||||||
|
|
||||||
import at.dhyan.open_imaging.GifDecoder;
|
import at.dhyan.open_imaging.GifDecoder;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import org.auraclient.auraclient.AuraClient;
|
import org.auraclient.auraclient.AuraClient;
|
||||||
import org.auraclient.auraclient.cloaks.utils.AnimatedCapeData;
|
import org.auraclient.auraclient.cloaks.utils.AnimatedCapeData;
|
||||||
import org.auraclient.auraclient.cloaks.utils.IdentifierUtils;
|
import org.auraclient.auraclient.cloaks.utils.IdentifierUtils;
|
||||||
import org.auraclient.auraclient.cloaks.utils.RandomUtils;
|
import org.auraclient.auraclient.cloaks.utils.RandomUtils;
|
||||||
import org.auraclient.auraclient.event.KeyInputHandler;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the cloak/cape system for Aura Client.
|
||||||
|
* Handles loading, caching, and animating player capes.
|
||||||
|
*/
|
||||||
public class Cloaks {
|
public class Cloaks {
|
||||||
private static final File capesFolder = new File(MinecraftClient.getInstance().runDirectory, "Capes");
|
private static final String CAPES_RESOURCE_PATH = "assets/auraclient/textures/capes/";
|
||||||
public static final List<String> list = new ArrayList<>();
|
private static final List<AnimatedCapeData> animatedCapeFrames = new ArrayList<>();
|
||||||
private static final List<AnimatedCapeData> anicape = new ArrayList<>();
|
private static int currentFrameIndex = 0;
|
||||||
private static int capeindex = 0;
|
private static long lastFrameTime = System.currentTimeMillis();
|
||||||
private static long mili = System.currentTimeMillis();
|
private static String lastCachedCape = "NoCache";
|
||||||
private static String lastCache = "NotCached";
|
|
||||||
|
public static final List<String> availableCapes = new ArrayList<>();
|
||||||
public static Identifier capeCacheIdentifier = null;
|
public static Identifier capeCacheIdentifier = null;
|
||||||
public static String cape = "";
|
public static final Map<String, String> playerCapes = new HashMap<>();
|
||||||
|
|
||||||
public static void initialize() {
|
/**
|
||||||
list.clear();
|
* Initializes the cloak system.
|
||||||
list.add("");
|
* Loads cape textures from resources.
|
||||||
if (capesFolder.mkdir()) {
|
*/
|
||||||
AuraClient.LOGGER.info("New Cape Folder Created");
|
public static void initialize() {
|
||||||
downloadCloakTextures();
|
availableCapes.clear();
|
||||||
} else {
|
availableCapes.add("");
|
||||||
AuraClient.LOGGER.info("Cape Folder Already Exists");
|
loadCloakTextures();
|
||||||
}
|
}
|
||||||
loadCloakTextures();
|
|
||||||
|
|
||||||
KeyInputHandler.register();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void downloadCloakTextures() {
|
|
||||||
// Todo: Download the cloak textures and put them in the Capes folder
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void loadCloakTextures() {
|
|
||||||
if (capesFolder.isDirectory()) {
|
|
||||||
for (final File fileEntry : Objects.requireNonNull(capesFolder.listFiles())) {
|
|
||||||
if (
|
|
||||||
fileEntry.getName().endsWith(".png") || fileEntry.getName().endsWith(".gif")
|
|
||||||
) {
|
|
||||||
list.add(fileEntry.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void tick() {
|
|
||||||
if (!lastCache.equals(cape)) {
|
|
||||||
if (!cape.isEmpty()) {
|
|
||||||
if (cape.endsWith(".gif")) {
|
|
||||||
try {
|
|
||||||
anicape.clear();
|
|
||||||
Identifier frameIdentifier;
|
|
||||||
File file = new File(capesFolder, cape);
|
|
||||||
final FileInputStream data = new FileInputStream(file);
|
|
||||||
final GifDecoder.GifImage gif = GifDecoder.read(data);
|
|
||||||
final int frameCount = gif.getFrameCount();
|
|
||||||
for (int i = 0; i < frameCount; i++) {
|
|
||||||
final BufferedImage img = gif.getFrame(i);
|
|
||||||
final int delay = gif.getDelay(i);
|
|
||||||
frameIdentifier = Identifier.of(AuraClient.MOD_ID, "capes_" + RandomUtils.randomStringLowercase(10));
|
|
||||||
IdentifierUtils.registerBufferedImageTexture(frameIdentifier, img);
|
|
||||||
anicape.add(new AnimatedCapeData(frameIdentifier, delay));
|
|
||||||
}
|
|
||||||
capeindex = 0;
|
|
||||||
capeCacheIdentifier = anicape.get(0).getId();
|
|
||||||
lastCache = cape;
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BufferedImage img = null;
|
|
||||||
File file = new File(capesFolder, cape);
|
|
||||||
try {
|
|
||||||
img = ImageIO.read(file);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
capeCacheIdentifier = Identifier.of(AuraClient.MOD_ID, "capes_" + cape.toLowerCase(Locale.ROOT).replace(' ', '_').replaceAll("[^a-z0-9/._-]", ""));
|
/**
|
||||||
IdentifierUtils.registerBufferedImageTexture(capeCacheIdentifier, img);
|
* Loads cloak textures from the resources.
|
||||||
lastCache = cape;
|
* Supports both static (.png) and animated (.gif) capes.
|
||||||
}
|
*/
|
||||||
} else {
|
private static void loadCloakTextures() {
|
||||||
capeCacheIdentifier = null;
|
// In a resource-based system, we would need to manually list available capes
|
||||||
lastCache = cape;
|
// For now, we can add default capes that we know exist in resources
|
||||||
}
|
// This would need to be updated when adding new capes to resources
|
||||||
} else {
|
availableCapes.add("glitch.png");
|
||||||
if (cape.endsWith(".gif")) {
|
}
|
||||||
if (capeindex > (anicape.size() - 1)) {
|
|
||||||
capeindex = 0;
|
/**
|
||||||
}
|
* Updates the cape animation state.
|
||||||
if (System.currentTimeMillis() > mili + anicape.get(capeindex).getDelay()) {
|
* Called every tick to handle animated capes.
|
||||||
mili = System.currentTimeMillis();
|
*/
|
||||||
capeCacheIdentifier = anicape.get(capeindex).getId();
|
public static void tick() {
|
||||||
capeindex++;
|
String currentCape = playerCapes.values().stream().findFirst().orElse("");
|
||||||
}
|
|
||||||
}
|
if (!lastCachedCape.equals(currentCape)) {
|
||||||
|
handleCapeChange(currentCape);
|
||||||
|
} else if (currentCape.endsWith(".gif")) {
|
||||||
|
updateAnimatedCape();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Handles loading and caching of a new cape texture.
|
||||||
|
* @param capeName Name of the cape file to load
|
||||||
|
*/
|
||||||
|
private static void handleCapeChange(String capeName) {
|
||||||
|
if (!capeName.isEmpty()) {
|
||||||
|
if (capeName.endsWith(".gif")) {
|
||||||
|
loadAnimatedCape(capeName);
|
||||||
|
} else {
|
||||||
|
loadStaticCape(capeName);
|
||||||
|
}
|
||||||
|
lastCachedCape = capeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads and processes an animated cape from a GIF file in resources.
|
||||||
|
* @param fileName Name of the GIF file to load
|
||||||
|
*/
|
||||||
|
private static void loadAnimatedCape(String fileName) {
|
||||||
|
try {
|
||||||
|
animatedCapeFrames.clear();
|
||||||
|
String resourcePath = CAPES_RESOURCE_PATH + fileName;
|
||||||
|
InputStream inputStream = Cloaks.class.getClassLoader().getResourceAsStream(resourcePath);
|
||||||
|
|
||||||
|
if (inputStream != null) {
|
||||||
|
GifDecoder.GifImage gif = GifDecoder.read(inputStream);
|
||||||
|
int frameCount = gif.getFrameCount();
|
||||||
|
|
||||||
|
for (int i = 0; i < frameCount; i++) {
|
||||||
|
BufferedImage frame = gif.getFrame(i);
|
||||||
|
int delay = gif.getDelay(i);
|
||||||
|
Identifier frameId = Identifier.of(AuraClient.MOD_ID,
|
||||||
|
"capes_" + RandomUtils.randomStringLowercase(10));
|
||||||
|
|
||||||
|
IdentifierUtils.registerBufferedImageTexture(frameId, frame);
|
||||||
|
animatedCapeFrames.add(new AnimatedCapeData(frameId, delay));
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFrameIndex = 0;
|
||||||
|
capeCacheIdentifier = animatedCapeFrames.get(0).getTextureId();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
AuraClient.LOGGER.error("Failed to load animated cape from resources: " + fileName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads and processes a static cape from a PNG file in resources.
|
||||||
|
* @param fileName Name of the PNG file to load
|
||||||
|
*/
|
||||||
|
private static void loadStaticCape(String fileName) {
|
||||||
|
try {
|
||||||
|
String resourcePath = CAPES_RESOURCE_PATH + fileName;
|
||||||
|
InputStream inputStream = Cloaks.class.getClassLoader().getResourceAsStream(resourcePath);
|
||||||
|
|
||||||
|
if (inputStream != null) {
|
||||||
|
BufferedImage image = ImageIO.read(inputStream);
|
||||||
|
|
||||||
|
String safeFileName = fileName.toLowerCase(Locale.ROOT)
|
||||||
|
.replace(' ', '_')
|
||||||
|
.replaceAll("[^a-z0-9/._-]", "");
|
||||||
|
|
||||||
|
capeCacheIdentifier = Identifier.of(AuraClient.MOD_ID, "capes_" + safeFileName);
|
||||||
|
IdentifierUtils.registerBufferedImageTexture(capeCacheIdentifier, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
AuraClient.LOGGER.error("Failed to load static cape from resources: " + fileName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current frame of an animated cape.
|
||||||
|
*/
|
||||||
|
private static void updateAnimatedCape() {
|
||||||
|
if (currentFrameIndex >= animatedCapeFrames.size()) {
|
||||||
|
currentFrameIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedCapeData currentFrame = animatedCapeFrames.get(currentFrameIndex);
|
||||||
|
if (System.currentTimeMillis() > lastFrameTime + currentFrame.getDelayMs()) {
|
||||||
|
lastFrameTime = System.currentTimeMillis();
|
||||||
|
capeCacheIdentifier = currentFrame.getTextureId();
|
||||||
|
currentFrameIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,20 +2,34 @@ package org.auraclient.auraclient.cloaks.utils;
|
|||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a single frame of an animated cape.
|
||||||
|
*/
|
||||||
public class AnimatedCapeData {
|
public class AnimatedCapeData {
|
||||||
private final Identifier id;
|
private final Identifier textureId;
|
||||||
private final int delay;
|
private final int delayMs;
|
||||||
|
|
||||||
public AnimatedCapeData(Identifier id, int delay) {
|
/**
|
||||||
this.id = id;
|
* Creates a new animated cape frame.
|
||||||
this.delay = delay;
|
* @param textureId The texture identifier for this frame
|
||||||
|
* @param delayMs The delay in milliseconds before the next frame
|
||||||
|
*/
|
||||||
|
public AnimatedCapeData(Identifier textureId, int delayMs) {
|
||||||
|
this.textureId = textureId;
|
||||||
|
this.delayMs = delayMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getId() {
|
/**
|
||||||
return id;
|
* @return The texture identifier for this frame
|
||||||
|
*/
|
||||||
|
public Identifier getTextureId() {
|
||||||
|
return textureId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDelay() {
|
/**
|
||||||
return delay;
|
* @return The delay in milliseconds before the next frame
|
||||||
|
*/
|
||||||
|
public int getDelayMs() {
|
||||||
|
return delayMs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,28 +2,47 @@ package org.auraclient.auraclient.cloaks.utils;
|
|||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class RandomUtils {
|
/**
|
||||||
|
* Utility class for generating random strings and numbers.
|
||||||
|
*/
|
||||||
|
public final class RandomUtils {
|
||||||
|
private static final String ALPHANUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
private static final String ALPHANUMERIC_LOWERCASE = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
private static final Random RANDOM = new Random();
|
||||||
|
|
||||||
|
private RandomUtils() {
|
||||||
|
// Prevent instantiation
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random string of specified length using given characters.
|
||||||
|
*/
|
||||||
private static String random(final int length, final char[] chars) {
|
private static String random(final int length, final char[] chars) {
|
||||||
final StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder sb = new StringBuilder(length);
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++) {
|
||||||
stringBuilder.append(chars[new Random().nextInt(chars.length)]);
|
sb.append(chars[RANDOM.nextInt(chars.length)]);
|
||||||
return stringBuilder.toString();
|
}
|
||||||
}
|
return sb.toString();
|
||||||
|
|
||||||
private static String random(final int length, final String chars) {
|
|
||||||
return random(length, chars.toCharArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random string of specified length using alphanumeric characters.
|
||||||
|
*/
|
||||||
public static String randomString(final int length) {
|
public static String randomString(final int length) {
|
||||||
return random(length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
return random(length, ALPHANUMERIC.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random lowercase string of specified length.
|
||||||
|
*/
|
||||||
public static String randomStringLowercase(final int length) {
|
public static String randomStringLowercase(final int length) {
|
||||||
return random(length, "0123456789abcdefghijklmnopqrstuvwxyz");
|
return random(length, ALPHANUMERIC_LOWERCASE.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random integer between min and max (inclusive).
|
||||||
|
*/
|
||||||
public static int randBetween(int min, int max) {
|
public static int randBetween(int min, int max) {
|
||||||
Random r = new Random();
|
return RANDOM.nextInt(max - min + 1) + min;
|
||||||
return r.nextInt(max - min) + min;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,18 +7,33 @@ import net.minecraft.client.util.InputUtil;
|
|||||||
import org.auraclient.auraclient.menus.MainMenu;
|
import org.auraclient.auraclient.menus.MainMenu;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles keyboard input events for the Aura Client.
|
||||||
|
* Manages keybindings and their associated actions.
|
||||||
|
*/
|
||||||
public class KeyInputHandler {
|
public class KeyInputHandler {
|
||||||
public static final String KEY_CATEGORY_CAPES = "key.category.auraclient";
|
private static final String KEY_CATEGORY = "key.category.auraclient";
|
||||||
public static final String KEY_MAIN_MENU = "key.auraclient.main_menu";
|
private static final String MAIN_MENU_KEY_ID = "key.auraclient.main_menu";
|
||||||
public static KeyBinding mainMenuKey;
|
private static final int DEFAULT_MENU_KEY = GLFW.GLFW_KEY_RIGHT_SHIFT;
|
||||||
|
|
||||||
|
private static KeyBinding mainMenuKeyBinding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all keybindings and their associated event handlers.
|
||||||
|
* Should be called during mod initialization.
|
||||||
|
*/
|
||||||
public static void register() {
|
public static void register() {
|
||||||
mainMenuKey = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
// Register the main menu key binding
|
||||||
KEY_MAIN_MENU, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_RIGHT_SHIFT, KEY_CATEGORY_CAPES
|
mainMenuKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
||||||
|
MAIN_MENU_KEY_ID,
|
||||||
|
InputUtil.Type.KEYSYM,
|
||||||
|
DEFAULT_MENU_KEY,
|
||||||
|
KEY_CATEGORY
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Register the event handler for the main menu key
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||||
if (mainMenuKey.wasPressed()) {
|
if (mainMenuKeyBinding.wasPressed()) {
|
||||||
client.setScreen(new MainMenu());
|
client.setScreen(new MainMenu());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,43 @@
|
|||||||
package org.auraclient.auraclient.menus;
|
package org.auraclient.auraclient.menus;
|
||||||
|
|
||||||
|
import org.auraclient.auraclient.AuraClient;
|
||||||
import org.auraclient.auraclient.cloaks.Cloaks;
|
import org.auraclient.auraclient.cloaks.Cloaks;
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
public class CloakSelector extends Screen {
|
public class CloakSelector extends Screen {
|
||||||
|
private TextFieldWidget playerNameField;
|
||||||
|
|
||||||
public CloakSelector() {
|
public CloakSelector() {
|
||||||
super(Text.literal("Cloaks"));
|
super(Text.literal("Cloaks"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
int y = ((this.height - (35 * (Cloaks.list.size()))) / 2);
|
// Add player name text field at the top
|
||||||
|
this.playerNameField = new TextFieldWidget(this.textRenderer,
|
||||||
|
(this.width - 200) / 2, 20, 200, 20, Text.literal("Player Name"));
|
||||||
|
this.playerNameField.setMaxLength(16);
|
||||||
|
addDrawableChild(this.playerNameField);
|
||||||
|
|
||||||
for (String cloak : Cloaks.list) {
|
// Calculate starting Y position for cloak buttons, accounting for text field
|
||||||
|
int y = ((this.height - (35 * (Cloaks.availableCapes.size()))) / 2) + 30;
|
||||||
|
|
||||||
|
for (String cloak : Cloaks.availableCapes) {
|
||||||
addDrawableChild(ButtonWidget.builder(Text.literal(cloak), (__) -> {
|
addDrawableChild(ButtonWidget.builder(Text.literal(cloak), (__) -> {
|
||||||
Cloaks.cape = cloak;
|
String playerName = this.playerNameField.getText();
|
||||||
|
if (!playerName.isEmpty() && !playerName.equals("Player Name")) {
|
||||||
|
if (cloak.isEmpty()) {
|
||||||
|
Cloaks.playerCapes.remove(playerName);
|
||||||
|
AuraClient.LOGGER.info("Cape removed for player: " + playerName);
|
||||||
|
} else {
|
||||||
|
Cloaks.playerCapes.put(playerName, cloak);
|
||||||
|
AuraClient.LOGGER.info("Cape set for player: " + playerName + " to " + cloak);
|
||||||
|
}
|
||||||
|
}
|
||||||
}).dimensions((this.width - 50) / 2, y, 50, 30).build());
|
}).dimensions((this.width - 50) / 2, y, 50, 30).build());
|
||||||
|
|
||||||
y += 35;
|
y += 35;
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ public class MainMenu extends Screen {
|
|||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
addDrawableChild(ButtonWidget.builder(Text.literal("Cloaks"), (_button) -> {
|
addDrawableChild(ButtonWidget.builder(Text.literal("Cloaks"), (_button) -> {
|
||||||
client.setScreen(new CloakSelector());
|
if (client.player != null) {
|
||||||
|
client.setScreen(new CloakSelector());
|
||||||
|
}
|
||||||
}).dimensions((this.width - 50) / 2, (this.height - 30) / 2, 50, 30).build());
|
}).dimensions((this.width - 50) / 2, (this.height - 30) / 2, 50, 30).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+26
-15
@@ -1,35 +1,46 @@
|
|||||||
package org.auraclient.auraclient.mixin;
|
package org.auraclient.auraclient.mixin;
|
||||||
|
|
||||||
import org.auraclient.auraclient.AuraClient;
|
|
||||||
import org.auraclient.auraclient.cloaks.Cloaks;
|
|
||||||
|
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
|
||||||
import net.minecraft.client.util.SkinTextures;
|
import net.minecraft.client.util.SkinTextures;
|
||||||
|
import org.auraclient.auraclient.cloaks.Cloaks;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin for handling custom cloaks in the AbstractClientPlayerEntity class.
|
||||||
|
* Injects custom cape textures for players who have them assigned.
|
||||||
|
*/
|
||||||
@Mixin(AbstractClientPlayerEntity.class)
|
@Mixin(AbstractClientPlayerEntity.class)
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
public class AbstractClientPlayerEntityMixin {
|
public class AbstractClientPlayerEntityMixin {
|
||||||
@Inject(at = @At("RETURN"), method = "getSkinTextures", cancellable = true)
|
|
||||||
private void getSkinTextures(CallbackInfoReturnable<SkinTextures> cir) {
|
|
||||||
// AbstractClientPlayerEntity player = (AbstractClientPlayerEntity) (Object) this;
|
|
||||||
|
|
||||||
if (((AbstractClientPlayerEntity) (Object) this) instanceof ClientPlayerEntity && Cloaks.capeCacheIdentifier != null) {
|
/**
|
||||||
// AuraClient.LOGGER.info("Rendering skin for: " + player.getUuid());
|
* Injects custom cape textures into the player's skin textures.
|
||||||
|
* @param cir Callback containing the original skin textures
|
||||||
|
*/
|
||||||
|
@Inject(
|
||||||
|
method = "getSkinTextures",
|
||||||
|
at = @At("RETURN"),
|
||||||
|
cancellable = true
|
||||||
|
)
|
||||||
|
private void getSkinTextures(CallbackInfoReturnable<SkinTextures> cir) {
|
||||||
|
AbstractClientPlayerEntity player = (AbstractClientPlayerEntity) (Object) this;
|
||||||
|
|
||||||
|
if (Cloaks.playerCapes.containsKey(player.getName().getString()) &&
|
||||||
|
Cloaks.capeCacheIdentifier != null) {
|
||||||
|
|
||||||
SkinTextures textures = cir.getReturnValue();
|
SkinTextures textures = cir.getReturnValue();
|
||||||
cir.setReturnValue(new SkinTextures(
|
cir.setReturnValue(new SkinTextures(
|
||||||
textures.texture(),
|
textures.texture(),
|
||||||
textures.textureUrl(),
|
textures.textureUrl(),
|
||||||
Cloaks.capeCacheIdentifier,
|
Cloaks.capeCacheIdentifier,
|
||||||
textures.elytraTexture(),
|
textures.elytraTexture(),
|
||||||
textures.model(),
|
textures.model(),
|
||||||
textures.secure()
|
textures.secure()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
package org.auraclient.auraclient.mixin;
|
package org.auraclient.auraclient.mixin;
|
||||||
|
|
||||||
import org.auraclient.auraclient.cloaks.Cloaks;
|
|
||||||
|
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import org.auraclient.auraclient.cloaks.Cloaks;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin for the MinecraftClient class.
|
||||||
|
* Handles the periodic updating of cloaks system.
|
||||||
|
*/
|
||||||
@Mixin(MinecraftClient.class)
|
@Mixin(MinecraftClient.class)
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
public class MinecraftClientMixin {
|
public class MinecraftClientMixin {
|
||||||
@Inject(at = @At("HEAD"), method = "tick")
|
|
||||||
|
/**
|
||||||
|
* Injects into the client tick to update cloaks.
|
||||||
|
* @param ci Callback info
|
||||||
|
*/
|
||||||
|
@Inject(
|
||||||
|
method = "tick",
|
||||||
|
at = @At("HEAD")
|
||||||
|
)
|
||||||
private void tick(CallbackInfo ci) {
|
private void tick(CallbackInfo ci) {
|
||||||
Cloaks.tick();
|
Cloaks.tick();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user