diff --git a/src/main/java/me/night0721/lilase/Lilase.java b/src/main/java/me/night0721/lilase/Lilase.java index efe4f9a..67c3ecf 100644 --- a/src/main/java/me/night0721/lilase/Lilase.java +++ b/src/main/java/me/night0721/lilase/Lilase.java @@ -20,6 +20,8 @@ import me.night0721.lilase.utils.Clock; import me.night0721.lilase.utils.KeyBindingManager; import me.night0721.lilase.utils.ScoreboardUtils; import me.night0721.lilase.utils.Utils; +import me.night0721.lilase.utils.capes.CapeDatabase; +import me.night0721.lilase.utils.capes.CapeManager; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiDisconnected; import net.minecraft.client.gui.GuiMainMenu; @@ -51,12 +53,13 @@ public class Lilase { private int tickAmount; private final Clock clock = new Clock(); public static RemoteControl remoteControl; + public static CapeDatabase capeDatabase = new CapeDatabase(); @Mod.EventHandler public void init(FMLInitializationEvent event) { (configHandler = new ConfigHandler()).init(); KeyBindingManager keyBindingManager = new KeyBindingManager(); - addToEventBus(this, keyBindingManager, new SniperFlipperEvents(), new ChatReceivedEvent(), new GUIRenderer()); + addToEventBus(this, keyBindingManager, new SniperFlipperEvents(), new ChatReceivedEvent(), new GUIRenderer(), new CapeManager()); EventManager.INSTANCE.register(this); // pageFlipper = new PageFlipper(); keyBindingManager.registerKeyBindings(); @@ -66,6 +69,7 @@ public class Lilase { webhook.setUsername("Lilase"); webhook.setAvatarUrl(icon); remoteControl = new RemoteControl(); + capeDatabase.init(); } private void addToEventBus(Object... objects) { diff --git a/src/main/java/me/night0721/lilase/utils/HWIDUtils.java b/src/main/java/me/night0721/lilase/utils/HWIDUtils.java new file mode 100644 index 0000000..f2df8a1 --- /dev/null +++ b/src/main/java/me/night0721/lilase/utils/HWIDUtils.java @@ -0,0 +1,25 @@ +package me.night0721.lilase.utils; + +import java.security.MessageDigest; + +public class HWIDUtils { + private static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = "0123456789ABCDEF".toCharArray()[v >>> 4]; + hexChars[j * 2 + 1] = "0123456789ABCDEF".toCharArray()[v & 0xF]; + } + return new String(hexChars); + } + + public static String getID() { + try { + MessageDigest hash = MessageDigest.getInstance("MD5"); + String s = System.getProperty("os.name") + System.getProperty("os.arch") + System.getProperty("os.version") + Runtime.getRuntime().availableProcessors() + System.getenv("PROCESSOR_IDENTIFIER") + System.getenv("PROCESSOR_REVISION") + System.getenv("USERNAME") + System.getenv("PROCESSOR_LEVEL") + System.getenv("windir"); + return bytesToHex(hash.digest(s.getBytes())); + } catch (Exception ignored) { + return ""; + } + } +} diff --git a/src/main/java/me/night0721/lilase/utils/capes/CapeDatabase.java b/src/main/java/me/night0721/lilase/utils/capes/CapeDatabase.java new file mode 100644 index 0000000..98238fc --- /dev/null +++ b/src/main/java/me/night0721/lilase/utils/capes/CapeDatabase.java @@ -0,0 +1,63 @@ +package me.night0721.lilase.utils.capes; + +import com.google.gson.JsonParser; +import me.night0721.lilase.Lilase; +import me.night0721.lilase.utils.HWIDUtils; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.util.ResourceLocation; + +import javax.imageio.ImageIO; +import javax.net.ssl.HttpsURLConnection; +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +/** + * Credits: Gabagooooooooooool + */ +public class CapeDatabase { + private final Map cachedCapeTextures = new HashMap<>(); + + public boolean userHasCape(String username) { + return cachedCapeTextures.containsKey(username.toLowerCase()); + } + + public ResourceLocation getUserCape(String username) { + return cachedCapeTextures.get(username.toLowerCase()); + } + + public void init() { + try { + URL url = new URL("https://api.night0721.me/api/v1/wl"); + StringBuilder result = new StringBuilder(); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("User-Agent", "night0721"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("Accept", "application/json"); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + for (String line; (line = reader.readLine()) != null; ) { + result.append(line); + } + } + new JsonParser().parse(result.toString()).getAsJsonArray().forEach(jsonElement -> { + String id = jsonElement.getAsJsonObject().get("id").getAsString(); + if (!id.equals(HWIDUtils.getID())) return; + String username = jsonElement.getAsJsonObject().get("username").getAsString(); + String capeUrl = jsonElement.getAsJsonObject().get("url").getAsString(); + try { + BufferedImage image = ImageIO.read(new URL(capeUrl)); + DynamicTexture texture = new DynamicTexture(image); + cachedCapeTextures.put(username.toLowerCase(), Lilase.mc.getTextureManager().getDynamicTextureLocation("Lilas_" + username, texture)); + } catch (IOException ignored) { + } + }); + } catch (IOException ignored) { + + } + } +} \ No newline at end of file diff --git a/src/main/java/me/night0721/lilase/utils/capes/CapeLayer.java b/src/main/java/me/night0721/lilase/utils/capes/CapeLayer.java new file mode 100644 index 0000000..85671ef --- /dev/null +++ b/src/main/java/me/night0721/lilase/utils/capes/CapeLayer.java @@ -0,0 +1,60 @@ +package me.night0721.lilase.utils.capes; + +import lombok.AllArgsConstructor; +import me.night0721.lilase.Lilase; +import me.night0721.lilase.utils.HWIDUtils; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderPlayer; +import net.minecraft.client.renderer.entity.layers.LayerRenderer; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; + +/** + * @author Revxrsal Gabagooooooooooool + * @version 1.1 + * Implemented from github.com/Revxrsal/SimpleCapes under Apache Commons 2.0 License + */ +@AllArgsConstructor +public class CapeLayer implements LayerRenderer { + private final RenderPlayer playerRenderer; + + @Override + public void doRenderLayer(AbstractClientPlayer entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale) { + ResourceLocation capeLoc = Lilase.capeDatabase.getUserCape(entity.getName()); + if (capeLoc == null) return; + if (!entity.isInvisible() && entity.isWearing(EnumPlayerModelParts.CAPE)) { + float f9 = entity.isSneaking() ? .1F : .14F; + float f10 = entity.isSneaking() ? .09F : 0F; + GlStateManager.color(1F, 1F, 1F, 1F); + this.playerRenderer.bindTexture(capeLoc); + GlStateManager.pushMatrix(); + GlStateManager.translate(0.0F, f10, f9); + double d0 = entity.prevChasingPosX + (entity.chasingPosX - entity.prevChasingPosX) * partialTicks - (entity.prevPosX + (entity.posX - entity.prevPosX) * partialTicks); + double d1 = entity.prevChasingPosY + (entity.chasingPosY - entity.prevChasingPosY) * partialTicks - (entity.prevPosY + (entity.posY - entity.prevPosY) * partialTicks); + double d2 = entity.prevChasingPosZ + (entity.chasingPosZ - entity.prevChasingPosZ) * partialTicks - (entity.prevPosZ + (entity.posZ - entity.prevPosZ) * partialTicks); + float f = entity.prevRenderYawOffset + (entity.renderYawOffset - entity.prevRenderYawOffset) * partialTicks; + double d3 = MathHelper.sin(f * .017453292F); + double d4 = -MathHelper.cos(f * .017453292F); + float f1 = (float) d1 * 10F; + f1 = MathHelper.clamp_float(f1, 3F, 32F); + float f2 = Math.max((float) (d0 * d3 + d2 * d4) * 100F, 0F); + float f3 = (float) (d0 * d4 - d2 * d3) * 100F; + float f4 = entity.prevCameraYaw + (entity.cameraYaw - entity.prevCameraYaw) * partialTicks; + f1 += MathHelper.sin((entity.prevDistanceWalkedModified + (entity.distanceWalkedModified - entity.prevDistanceWalkedModified) * partialTicks) * 6F) * 32F * f4; + if (entity.isSneaking()) f1 += 20F; + GlStateManager.rotate(5F + f2 / 2F + f1, 1F, 0F, 0F); + GlStateManager.rotate(f3 / 2F, 0F, 0F, 1F); + GlStateManager.rotate(-f3 / 2F, 0F, 1F, 0F); + GlStateManager.rotate(180F, 0F, 1F, 0F); + this.playerRenderer.getMainModel().renderCape(.0625F); + GlStateManager.popMatrix(); + } + } + + @Override + public boolean shouldCombineTextures() { + return false; + } +} diff --git a/src/main/java/me/night0721/lilase/utils/capes/CapeManager.java b/src/main/java/me/night0721/lilase/utils/capes/CapeManager.java new file mode 100644 index 0000000..2bb25b2 --- /dev/null +++ b/src/main/java/me/night0721/lilase/utils/capes/CapeManager.java @@ -0,0 +1,19 @@ +package me.night0721.lilase.utils.capes; + +import me.night0721.lilase.Lilase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +/** + * Credits: Gabagooooooooooool + */ +public class CapeManager { + @SubscribeEvent + public void onJoin(EntityJoinWorldEvent event) { + if (event.entity instanceof EntityPlayer) { + Lilase.mc.gameSettings.setModelPartEnabled(EnumPlayerModelParts.CAPE, true); + Lilase.mc.getRenderManager().getSkinMap().values().forEach(p -> p.addLayer(new CapeLayer(p))); + } + } +} \ No newline at end of file