Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,56 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class CustomSkin {
public final String name;
public final byte[] texture;
public SkinModel model;
private EaglerSkinTexture textureInstance;
private ResourceLocation resourceLocation;
private static int texId = 0;
public CustomSkin(String name, byte[] texture, SkinModel model) {
this.name = name;
this.texture = texture;
this.model = model;
this.textureInstance = new EaglerSkinTexture(texture, model.width, model.height);
this.resourceLocation = null;
}
public void load() {
if(resourceLocation == null) {
resourceLocation = new ResourceLocation("eagler:skins/custom/tex_" + texId++);
Minecraft.getMinecraft().getTextureManager().loadTexture(resourceLocation, textureInstance);
}
}
public ResourceLocation getResource() {
return resourceLocation;
}
public void delete() {
if(resourceLocation != null) {
Minecraft.getMinecraft().getTextureManager().deleteTexture(resourceLocation);
resourceLocation = null;
}
}
}

View File

@ -0,0 +1,78 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public enum DefaultSkins {
DEFAULT_STEVE(0, "Default Steve", new ResourceLocation("eagler:skins/01.default_steve.png"), SkinModel.STEVE),
DEFAULT_ALEX(1, "Default Alex", new ResourceLocation("eagler:skins/02.default_alex.png"), SkinModel.ALEX),
TENNIS_STEVE(2, "Tennis Steve", new ResourceLocation("eagler:skins/03.tennis_steve.png"), SkinModel.STEVE),
TENNIS_ALEX(3, "Tennis Alex", new ResourceLocation("eagler:skins/04.tennis_alex.png"), SkinModel.ALEX),
TUXEDO_STEVE(4, "Tuxedo Steve", new ResourceLocation("eagler:skins/05.tuxedo_steve.png"), SkinModel.STEVE),
TUXEDO_ALEX(5, "Tuxedo Alex", new ResourceLocation("eagler:skins/06.tuxedo_alex.png"), SkinModel.ALEX),
ATHLETE_STEVE(6, "Athlete Steve", new ResourceLocation("eagler:skins/07.athlete_steve.png"), SkinModel.STEVE),
ATHLETE_ALEX(7, "Athlete Alex", new ResourceLocation("eagler:skins/08.athlete_alex.png"), SkinModel.ALEX),
CYCLIST_STEVE(8, "Cyclist Steve", new ResourceLocation("eagler:skins/09.cyclist_steve.png"), SkinModel.STEVE),
CYCLIST_ALEX(9, "Cyclist Alex", new ResourceLocation("eagler:skins/10.cyclist_alex.png"), SkinModel.ALEX),
BOXER_STEVE(10, "Boxer Steve", new ResourceLocation("eagler:skins/11.boxer_steve.png"), SkinModel.STEVE),
BOXER_ALEX(11, "Boxer Alex", new ResourceLocation("eagler:skins/12.boxer_alex.png"), SkinModel.ALEX),
PRISONER_STEVE(12, "Prisoner Steve", new ResourceLocation("eagler:skins/13.prisoner_steve.png"), SkinModel.STEVE),
PRISONER_ALEX(13, "Prisoner Alex", new ResourceLocation("eagler:skins/14.prisoner_alex.png"), SkinModel.ALEX),
SCOTTISH_STEVE(14, "Scottish Steve", new ResourceLocation("eagler:skins/15.scottish_steve.png"), SkinModel.STEVE),
SCOTTISH_ALEX(15, "Scottish Alex", new ResourceLocation("eagler:skins/16.scottish_alex.png"), SkinModel.ALEX),
DEVELOPER_STEVE(16, "Developer Steve", new ResourceLocation("eagler:skins/17.developer_steve.png"), SkinModel.STEVE),
DEVELOPER_ALEX(17, "Developer Alex", new ResourceLocation("eagler:skins/18.developer_alex.png"), SkinModel.ALEX),
HEROBRINE(18, "Herobrine", new ResourceLocation("eagler:skins/19.herobrine.png"), SkinModel.ZOMBIE),
NOTCH(19, "Notch", new ResourceLocation("eagler:skins/20.notch.png"), SkinModel.STEVE),
CREEPER(20, "Creeper", new ResourceLocation("eagler:skins/21.creeper.png"), SkinModel.STEVE),
ZOMBIE(21, "Zombie", new ResourceLocation("eagler:skins/22.zombie.png"), SkinModel.ZOMBIE),
PIG(22, "Pig", new ResourceLocation("eagler:skins/23.pig.png"), SkinModel.STEVE),
MOOSHROOM(23, "Mooshroom", new ResourceLocation("eagler:skins/24.mooshroom.png"), SkinModel.STEVE);
public static final DefaultSkins[] defaultSkinsMap = new DefaultSkins[24];
public final int id;
public final String name;
public final ResourceLocation location;
public final SkinModel model;
private DefaultSkins(int id, String name, ResourceLocation location, SkinModel model) {
this.id = id;
this.name = name;
this.location = location;
this.model = model;
}
public static DefaultSkins getSkinFromId(int id) {
DefaultSkins e = null;
if(id >= 0 && id < defaultSkinsMap.length) {
e = defaultSkinsMap[id];
}
if(e != null) {
return e;
}else {
return DEFAULT_STEVE;
}
}
static {
DefaultSkins[] skins = values();
for(int i = 0; i < skins.length; ++i) {
defaultSkinsMap[skins[i].id] = skins[i];
}
}
}

View File

@ -0,0 +1,251 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerProfile {
private static String username;
public static int presetSkinId;
public static int customSkinId;
public static final List<CustomSkin> customSkins = new ArrayList();
public static final EaglercraftRandom rand;
public static ResourceLocation getActiveSkinResourceLocation() {
if(presetSkinId == -1) {
if(customSkinId >= 0 && customSkinId < customSkins.size()) {
return customSkins.get(customSkinId).getResource();
}else {
customSkinId = -1;
presetSkinId = 0;
return DefaultSkins.defaultSkinsMap[0].location;
}
}else {
if(presetSkinId >= 0 && presetSkinId < DefaultSkins.defaultSkinsMap.length) {
return DefaultSkins.defaultSkinsMap[presetSkinId].location;
}else {
presetSkinId = 0;
return DefaultSkins.defaultSkinsMap[0].location;
}
}
}
public static SkinModel getActiveSkinModel() {
if(presetSkinId == -1) {
if(customSkinId >= 0 && customSkinId < customSkins.size()) {
return customSkins.get(customSkinId).model;
}else {
customSkinId = -1;
presetSkinId = 0;
return DefaultSkins.defaultSkinsMap[0].model;
}
}else {
if(presetSkinId >= 0 && presetSkinId < DefaultSkins.defaultSkinsMap.length) {
return DefaultSkins.defaultSkinsMap[presetSkinId].model;
}else {
presetSkinId = 0;
return DefaultSkins.defaultSkinsMap[0].model;
}
}
}
public static EaglercraftUUID getPlayerUUID() {
return Minecraft.getMinecraft().getSession().getProfile().getId();
}
public static String getName() {
return username;
}
public static void setName(String str) {
username = str;
Minecraft mc = Minecraft.getMinecraft();
if(mc != null) {
mc.getSession().reset();
}
}
public static byte[] getSkinPacket() throws IOException {
if(presetSkinId == -1) {
if(customSkinId >= 0 && customSkinId < customSkins.size()) {
return SkinPackets.writeMySkinCustom(customSkins.get(customSkinId));
}else {
customSkinId = -1;
presetSkinId = 0;
return SkinPackets.writeMySkinPreset(0);
}
}else {
if(presetSkinId >= 0 && presetSkinId < DefaultSkins.defaultSkinsMap.length) {
return SkinPackets.writeMySkinPreset(presetSkinId);
}else {
presetSkinId = 0;
return SkinPackets.writeMySkinPreset(0);
}
}
}
private static boolean doesSkinExist(String name) {
for(int i = 0, l = customSkins.size(); i < l; ++i) {
if(customSkins.get(i).name.equalsIgnoreCase(name)) {
return true;
}
}
return false;
}
public static int addCustomSkin(String fileName, byte[] rawSkin) {
if(doesSkinExist(fileName)) {
String newName;
int i = 2;
while(doesSkinExist(newName = fileName + " (" + i + ")")) {
++i;
}
fileName = newName;
}
CustomSkin newSkin = new CustomSkin(fileName, rawSkin, SkinModel.STEVE);
newSkin.load();
int r = customSkins.size();
customSkins.add(newSkin);
return r;
}
public static void clearCustomSkins() {
for(int i = 0, l = customSkins.size(); i < l; ++i) {
customSkins.get(i).delete();
}
customSkins.clear();
}
public static void read() {
byte[] profileStorage = EagRuntime.getStorage("p");
if (profileStorage == null) {
return;
}
NBTTagCompound profile;
try {
profile = CompressedStreamTools.readCompressed(new EaglerInputStream(profileStorage));
}catch(IOException ex) {
return;
}
if (profile == null || profile.hasNoTags()) {
return;
}
presetSkinId = profile.getInteger("presetSkin");
customSkinId = profile.getInteger("customSkin");
String loadUsername = profile.getString("username").trim();
if(!loadUsername.isEmpty()) {
username = loadUsername.replaceAll("[^A-Za-z0-9]", "_");
}
clearCustomSkins();
NBTTagList skinsList = profile.getTagList("skins", 10);
for(int i = 0, l = skinsList.tagCount(); i < l; ++i) {
NBTTagCompound skin = skinsList.getCompoundTagAt(i);
String skinName = skin.getString("name");
byte[] skinData = skin.getByteArray("data");
if(skinData.length != 16384) continue;
for(int y = 20; y < 32; ++y) {
for(int x = 16; x < 40; ++x) {
skinData[(y << 8) | (x << 2)] = (byte)0xff;
}
}
int skinModel = skin.getByte("model");
CustomSkin newSkin = new CustomSkin(skinName, skinData, SkinModel.getModelFromId(skinModel));
newSkin.load();
customSkins.add(newSkin);
}
if(presetSkinId == -1) {
if(customSkinId < 0 || customSkinId >= customSkins.size()) {
presetSkinId = 0;
customSkinId = -1;
}
}else {
customSkinId = -1;
if(presetSkinId < 0 || presetSkinId >= DefaultSkins.defaultSkinsMap.length) {
presetSkinId = 0;
}
}
}
public static void write() {
NBTTagCompound profile = new NBTTagCompound();
profile.setInteger("presetSkin", presetSkinId);
profile.setInteger("customSkin", customSkinId);
profile.setString("username", username);
NBTTagList skinsList = new NBTTagList();
for(int i = 0, l = customSkins.size(); i < l; ++i) {
CustomSkin sk = customSkins.get(i);
NBTTagCompound skin = new NBTTagCompound();
skin.setString("name", sk.name);
skin.setByteArray("data", sk.texture);
skin.setByte("model", (byte)sk.model.id);
skinsList.appendTag(skin);
}
profile.setTag("skins", skinsList);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
try {
CompressedStreamTools.writeCompressed(profile, bao);
} catch (IOException e) {
return;
}
EagRuntime.setStorage("p", bao.toByteArray());
}
static {
String[] defaultNames = new String[] {
"Yeeish", "Yeeish", "Yee", "Yee", "Yeer", "Yeeler", "Eagler", "Eagl",
"Darver", "Darvler", "Vool", "Vigg", "Vigg", "Deev", "Yigg", "Yeeg"
};
rand = new EaglercraftRandom();
do {
username = defaultNames[rand.nextInt(defaultNames.length)] + defaultNames[rand.nextInt(defaultNames.length)] + (100 + rand.nextInt(900));
}while(username.length() > 16);
setName(username);
presetSkinId = rand.nextInt(DefaultSkins.defaultSkinsMap.length);
customSkinId = -1;
}
}

View File

@ -0,0 +1,94 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
import net.minecraft.client.renderer.texture.ITextureObject;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.IResourceManager;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerSkinTexture implements ITextureObject {
private final int[] pixels;
private final int width;
private final int height;
private int textureId = -1;
public EaglerSkinTexture(int[] pixels, int width, int height) {
if(pixels.length != width * height) {
throw new IllegalArgumentException("Wrong data length " + pixels.length * 4 + " for " + width + "x" + height + " texture");
}
this.pixels = pixels;
this.width = width;
this.height = height;
}
public EaglerSkinTexture(byte[] pixels, int width, int height) {
if(pixels.length != width * height * 4) {
throw new IllegalArgumentException("Wrong data length " + pixels.length + " for " + width + "x" + height + " texture");
}
int[] p = new int[pixels.length >> 2];
for(int i = 0, j; i < p.length; ++i) {
j = i << 2;
p[i] = (((int) pixels[j] & 0xFF) << 24) | (((int) pixels[j + 1] & 0xFF) << 16)
| (((int) pixels[j + 2] & 0xFF) << 8) | ((int) pixels[j + 3] & 0xFF);
}
this.pixels = p;
this.width = width;
this.height = height;
}
public void copyPixelsIn(int[] pixels) {
if(this.pixels.length != pixels.length) {
throw new IllegalArgumentException("Tried to copy " + pixels.length + " pixels into a " + this.pixels.length + " pixel texture");
}
System.arraycopy(pixels, 0, this.pixels, 0, pixels.length);
if(textureId != -1) {
TextureUtil.uploadTextureImageAllocate(textureId, new ImageData(width, height, pixels, true), false, false);
}
}
@Override
public void loadTexture(IResourceManager var1) throws IOException {
if(textureId == -1) {
textureId = GlStateManager.generateTexture();
TextureUtil.uploadTextureImageAllocate(textureId, new ImageData(width, height, pixels, true), false, false);
}
}
@Override
public int getGlTextureId() {
return textureId;
}
@Override
public void setBlurMipmap(boolean var1, boolean var2) {
// no
}
@Override
public void restoreLastBlurMipmap() {
// no
}
public void free() {
GlStateManager.deleteTexture(textureId);
textureId = -1;
}
}

View File

@ -0,0 +1,123 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformNetworking;
import net.lax1dude.eaglercraft.v1_8.socket.ConnectionHandshake;
import net.lax1dude.eaglercraft.v1_8.socket.HandshakePacketTypes;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.client.resources.I18n;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class GuiAuthenticationScreen extends GuiScreen {
private final GuiConnecting retAfterAuthScreen;
private final GuiScreen parent;
private GuiButton continueButton;
private final String message;
private GuiPasswordTextField password;
private int authTypeForWarning = Integer.MAX_VALUE;
private boolean allowPlaintext = false;
public GuiAuthenticationScreen(GuiConnecting retAfterAuthScreen, GuiScreen parent, String message) {
this.retAfterAuthScreen = retAfterAuthScreen;
this.parent = parent;
String authRequired = HandshakePacketTypes.AUTHENTICATION_REQUIRED;
if(message.startsWith(authRequired)) {
message = message.substring(authRequired.length()).trim();
}
if(message.length() > 0 && message.charAt(0) == '[') {
int idx = message.indexOf(']', 1);
if(idx != -1) {
String authType = message.substring(1, idx);
int type = Integer.MAX_VALUE;
try {
type = Integer.parseInt(authType);
}catch(NumberFormatException ex) {
}
if(type != Integer.MAX_VALUE) {
authTypeForWarning = type;
message = message.substring(idx + 1).trim();
}
}
}
this.message = message;
}
public void initGui() {
if(authTypeForWarning != Integer.MAX_VALUE) {
GuiScreen scr = ConnectionHandshake.displayAuthProtocolConfirm(authTypeForWarning, parent, this);
authTypeForWarning = Integer.MAX_VALUE;
if(scr != null) {
mc.displayGuiScreen(scr);
allowPlaintext = true;
return;
}
}
Keyboard.enableRepeatEvents(true);
this.buttonList.clear();
this.buttonList.add(continueButton = new GuiButton(1, this.width / 2 - 100, this.height / 4 + 80 + 12,
I18n.format("auth.continue", new Object[0])));
continueButton.enabled = false;
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 80 + 37,
I18n.format("gui.cancel", new Object[0])));
this.password = new GuiPasswordTextField(2, this.fontRendererObj, this.width / 2 - 100, this.height / 4 + 40, 200, 20); // 116
this.password.setFocused(true);
this.password.setCanLoseFocus(false);
}
public void onGuiClosed() {
Keyboard.enableRepeatEvents(false);
}
protected void actionPerformed(GuiButton parGuiButton) {
if(parGuiButton.id == 1) {
this.mc.displayGuiScreen(new GuiConnecting(retAfterAuthScreen, password.getText()));
}else {
this.mc.displayGuiScreen(parent);
if (!PlatformNetworking.playConnectionState().isClosed()) {
PlatformNetworking.playDisconnect();
}
}
}
public void drawScreen(int i, int j, float var3) {
drawBackground(0);
this.password.drawTextBox();
this.drawCenteredString(this.fontRendererObj, I18n.format("auth.required", new Object[0]), this.width / 2,
this.height / 4 - 5, 16777215);
this.drawCenteredString(this.fontRendererObj, message, this.width / 2, this.height / 4 + 15, 0xAAAAAA);
super.drawScreen(i, j, var3);
}
protected void keyTyped(char parChar1, int parInt1) {
String pass = password.getText();
if(parInt1 == KeyboardConstants.KEY_RETURN && pass.length() > 0) {
this.mc.displayGuiScreen(new GuiConnecting(retAfterAuthScreen, pass, allowPlaintext));
}else {
this.password.textboxKeyTyped(parChar1, parInt1);
this.continueButton.enabled = password.getText().length() > 0;
}
}
protected void mouseClicked(int parInt1, int parInt2, int parInt3) {
super.mouseClicked(parInt1, parInt2, parInt3);
this.password.mouseClicked(parInt1, parInt2, parInt3);
}
}

View File

@ -0,0 +1,56 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiTextField;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class GuiPasswordTextField extends GuiTextField {
public GuiPasswordTextField(int componentId, FontRenderer fontrendererObj, int x, int y, int par5Width,
int par6Height) {
super(componentId, fontrendererObj, x, y, par5Width, par6Height);
}
public void drawTextBox() {
String oldText = text;
text = stars(text.length());
super.drawTextBox();
text = oldText;
}
public void mouseClicked(int parInt1, int parInt2, int parInt3) {
String oldText = text;
text = stars(text.length());
super.mouseClicked(parInt1, parInt2, parInt3);
text = oldText;
}
public static String stars(int len) {
return new String(STARS, 0, len > STARS.length ? STARS.length : len);
}
private static final char[] STARS = new char[] { '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*',
'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*' };
}

View File

@ -0,0 +1,463 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.Keyboard;
import net.lax1dude.eaglercraft.v1_8.Mouse;
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ResourceLocation;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.io.IOException;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class GuiScreenEditProfile extends GuiScreen {
private final GuiScreen parent;
private GuiTextField usernameField;
private boolean dropDownOpen = false;
private String[] dropDownOptions;
private int slotsVisible = 0;
private int selectedSlot = 0;
private int scrollPos = -1;
private int skinsHeight = 0;
private boolean dragging = false;
private int mousex = 0;
private int mousey = 0;
private boolean newSkinWaitSteveOrAlex = false;
private static final ResourceLocation eaglerGui = new ResourceLocation("eagler:gui/eagler_gui.png");
protected String screenTitle = "Edit Profile";
public GuiScreenEditProfile(GuiScreen parent) {
this.parent = parent;
updateOptions();
}
public void initGui() {
Keyboard.enableRepeatEvents(true);
screenTitle = I18n.format("editProfile.title");
usernameField = new GuiTextField(0, fontRendererObj, width / 2 - 20 + 1, height / 6 + 24 + 1, 138, 20);
usernameField.setFocused(true);
usernameField.setText(EaglerProfile.getName());
selectedSlot = EaglerProfile.presetSkinId == -1 ? EaglerProfile.customSkinId : (EaglerProfile.presetSkinId + EaglerProfile.customSkins.size());
buttonList.add(new GuiButton(0, width / 2 - 100, height / 6 + 168, I18n.format("gui.done")));
buttonList.add(new GuiButton(1, width / 2 - 21, height / 6 + 110, 71, 20, I18n.format("editProfile.addSkin")));
buttonList.add(new GuiButton(2, width / 2 - 21 + 71, height / 6 + 110, 72, 20, I18n.format("editProfile.clearSkin")));
}
private void updateOptions() {
int numCustom = EaglerProfile.customSkins.size();
String[] n = new String[numCustom + DefaultSkins.defaultSkinsMap.length];
for(int i = 0; i < numCustom; ++i) {
n[i] = EaglerProfile.customSkins.get(i).name;
}
int numDefault = DefaultSkins.defaultSkinsMap.length;
for(int j = 0; j < numDefault; ++j) {
n[numCustom + j] = DefaultSkins.defaultSkinsMap[j].name;
}
dropDownOptions = n;
}
public void drawScreen(int mx, int my, float partialTicks) {
drawDefaultBackground();
drawCenteredString(fontRendererObj, screenTitle, width / 2, 15, 16777215);
drawString(fontRendererObj, I18n.format("editProfile.username"), width / 2 - 20, height / 6 + 8, 10526880);
drawString(fontRendererObj, I18n.format("editProfile.playerSkin"), width / 2 - 20, height / 6 + 66, 10526880);
mousex = mx;
mousey = my;
int skinX = width / 2 - 120;
int skinY = height / 6 + 8;
int skinWidth = 80;
int skinHeight = 130;
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xFFA0A0A0);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, 0xFF000015);
int skid = selectedSlot - EaglerProfile.customSkins.size();
if(skid < 0) {
skid = 0;
}
usernameField.drawTextBox();
if(dropDownOpen || newSkinWaitSteveOrAlex) {
super.drawScreen(0, 0, partialTicks);
}else {
super.drawScreen(mx, my, partialTicks);
}
skinX = width / 2 - 20;
skinY = height / 6 + 82;
skinWidth = 140;
skinHeight = 22;
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, -6250336);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 21, skinY + skinHeight - 1, -16777216);
drawRect(skinX + skinWidth - 20, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, -16777216);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
mc.getTextureManager().bindTexture(eaglerGui);
drawTexturedModalRect(skinX + skinWidth - 18, skinY + 3, 0, 0, 16, 16);
drawString(fontRendererObj, dropDownOptions[selectedSlot], skinX + 5, skinY + 7, 14737632);
skinX = width / 2 - 20;
skinY = height / 6 + 103;
skinWidth = 140;
skinHeight = (height - skinY - 10);
slotsVisible = (skinHeight / 10);
if(slotsVisible > dropDownOptions.length) slotsVisible = dropDownOptions.length;
skinHeight = slotsVisible * 10 + 7;
skinsHeight = skinHeight;
if(scrollPos == -1) {
scrollPos = selectedSlot - 2;
}
if(scrollPos > (dropDownOptions.length - slotsVisible)) {
scrollPos = (dropDownOptions.length - slotsVisible);
}
if(scrollPos < 0) {
scrollPos = 0;
}
if(dropDownOpen) {
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, -6250336);
drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, -16777216);
for(int i = 0; i < slotsVisible; i++) {
if(i + scrollPos < dropDownOptions.length) {
if(selectedSlot == i + scrollPos) {
drawRect(skinX + 1, skinY + i*10 + 4, skinX + skinWidth - 1, skinY + i*10 + 14, 0x77ffffff);
}else if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i*10 + 5) && my < (skinY + i*10 + 15)) {
drawRect(skinX + 1, skinY + i*10 + 4, skinX + skinWidth - 1, skinY + i*10 + 14, 0x55ffffff);
}
drawString(fontRendererObj, dropDownOptions[i + scrollPos], skinX + 5, skinY + 5 + i*10, 14737632);
}
}
int scrollerSize = skinHeight * slotsVisible / dropDownOptions.length;
int scrollerPos = skinHeight * scrollPos / dropDownOptions.length;
drawRect(skinX + skinWidth - 4, skinY + scrollerPos + 1, skinX + skinWidth - 1, skinY + scrollerPos + scrollerSize, 0xff888888);
}
int xx = width / 2 - 80;
int yy = height / 6 + 130;
int numberOfCustomSkins = EaglerProfile.customSkins.size();
if(newSkinWaitSteveOrAlex && selectedSlot < numberOfCustomSkins) {
skinWidth = 70;
skinHeight = 120;
CustomSkin newSkin = EaglerProfile.customSkins.get(selectedSlot);
GlStateManager.clear(GL_DEPTH_BUFFER_BIT);
skinX = width / 2 - 90;
skinY = height / 4;
xx = skinX + 35;
yy = skinY + 117;
boolean mouseOver = mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight;
int cc = mouseOver ? 0xFFDDDD99 : 0xFF555555;
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
drawRect(0, 0, width, height, 0xbb000000);
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xbb000000);
GlStateManager.disableBlend();
drawRect(skinX, skinY, skinX + 1, skinY + skinHeight, cc);
drawRect(skinX, skinY, skinX + skinWidth, skinY + 1, cc);
drawRect(skinX + skinWidth - 1, skinY, skinX + skinWidth, skinY + skinHeight, cc);
drawRect(skinX, skinY + skinHeight - 1, skinX + skinWidth, skinY + skinHeight, cc);
if(mouseOver) {
drawCenteredString(fontRendererObj, "Steve", skinX + skinWidth / 2, skinY + skinHeight + 6, cc);
}
mc.getTextureManager().bindTexture(newSkin.getResource());
SkinPreviewRenderer.renderBiped(xx, yy, mx, my, SkinModel.STEVE);
skinX = width / 2 + 20;
skinY = height / 4;
xx = skinX + 35;
yy = skinY + 117;
mouseOver = mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight;
cc = mouseOver ? 0xFFDDDD99 : 0xFF555555;
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xbb000000);
GlStateManager.disableBlend();
drawRect(skinX, skinY, skinX + 1, skinY + skinHeight, cc);
drawRect(skinX, skinY, skinX + skinWidth, skinY + 1, cc);
drawRect(skinX + skinWidth - 1, skinY, skinX + skinWidth, skinY + skinHeight, cc);
drawRect(skinX, skinY + skinHeight - 1, skinX + skinWidth, skinY + skinHeight, cc);
if(mouseOver) {
drawCenteredString(fontRendererObj, "Alex", skinX + skinWidth / 2, skinY + skinHeight + 8, cc);
}
mc.getTextureManager().bindTexture(newSkin.getResource());
SkinPreviewRenderer.renderBiped(xx, yy, mx, my, SkinModel.ALEX);
}else {
skinX = this.width / 2 - 120;
skinY = this.height / 6 + 8;
skinWidth = 80;
skinHeight = 130;
ResourceLocation texture;
SkinModel model;
if(selectedSlot < numberOfCustomSkins) {
CustomSkin customSkin = EaglerProfile.customSkins.get(selectedSlot);
texture = customSkin.getResource();
model = customSkin.model;
}else {
DefaultSkins defaultSkin = DefaultSkins.defaultSkinsMap[selectedSlot - numberOfCustomSkins];
texture = defaultSkin.location;
model = defaultSkin.model;
}
mc.getTextureManager().bindTexture(texture);
SkinPreviewRenderer.renderBiped(xx, yy, newSkinWaitSteveOrAlex ? width / 2 : mx, newSkinWaitSteveOrAlex ? height / 2 : my, model);
}
}
public void handleMouseInput() throws IOException {
super.handleMouseInput();
if(dropDownOpen) {
int var1 = Mouse.getEventDWheel();
if(var1 < 0) {
scrollPos += 3;
}
if(var1 > 0) {
scrollPos -= 3;
if(scrollPos < 0) {
scrollPos = 0;
}
}
}
}
protected void actionPerformed(GuiButton par1GuiButton) {
if(!dropDownOpen) {
if(par1GuiButton.id == 0) {
safeProfile();
this.mc.displayGuiScreen((GuiScreen) parent);
}else if(par1GuiButton.id == 1) {
EagRuntime.displayFileChooser("image/png", "png");
}else if(par1GuiButton.id == 2) {
EaglerProfile.clearCustomSkins();
safeProfile();
updateOptions();
selectedSlot = 0;
}
}
}
public void updateScreen() {
usernameField.updateCursorCounter();
if(EagRuntime.fileChooserHasResult()) {
FileChooserResult result = EagRuntime.getFileChooserResult();
if(result != null) {
ImageData loadedSkin = ImageData.loadImageFile(result.fileData);
if(loadedSkin != null) {
boolean isLegacy = loadedSkin.width == 64 && loadedSkin.height == 32;
boolean isModern = loadedSkin.width == 64 && loadedSkin.height == 64;
if(isLegacy) {
ImageData newSkin = new ImageData(64, 64, true);
SkinConverter.convert64x32to64x64(loadedSkin, newSkin);
loadedSkin = newSkin;
isModern = true;
}
if(isModern) {
byte[] rawSkin = new byte[16384];
for(int i = 0, j, k; i < 4096; ++i) {
j = i << 2;
k = loadedSkin.pixels[i];
rawSkin[j] = (byte)(k >> 24);
rawSkin[j + 1] = (byte)(k >> 16);
rawSkin[j + 2] = (byte)(k >> 8);
rawSkin[j + 3] = (byte)(k & 0xFF);
}
for(int y = 20; y < 32; ++y) {
for(int x = 16; x < 40; ++x) {
rawSkin[(y << 8) | (x << 2)] = (byte)0xff;
}
}
int k;
if((k = EaglerProfile.addCustomSkin(result.fileName, rawSkin)) != -1) {
selectedSlot = k;
newSkinWaitSteveOrAlex = true;
updateOptions();
safeProfile();
}
}else {
EagRuntime.showPopup("The selected image '" + result.fileName + "' is not the right size!\nEaglercraft only supports 64x32 or 64x64 skins");
}
}else {
EagRuntime.showPopup("The selected file '" + result.fileName + "' is not a PNG file!");
}
}
}
if(dropDownOpen) {
if(Mouse.isButtonDown(0)) {
int skinX = width / 2 - 20;
int skinY = height / 6 + 103;
int skinWidth = 140;
if(mousex >= (skinX + skinWidth - 10) && mousex < (skinX + skinWidth) && mousey >= skinY && mousey < (skinY + skinsHeight)) {
dragging = true;
}
if(dragging) {
int scrollerSize = skinsHeight * slotsVisible / dropDownOptions.length;
scrollPos = (mousey - skinY - (scrollerSize / 2)) * dropDownOptions.length / skinsHeight;
}
}else {
dragging = false;
}
}else {
dragging = false;
}
}
public void onGuiClosed() {
Keyboard.enableRepeatEvents(false);
}
protected void keyTyped(char c, int k) {
usernameField.textboxKeyTyped(c, k);
String text = usernameField.getText();
if(text.length() > 16) text = text.substring(0, 16);
text = text.replaceAll("[^A-Za-z0-9]", "_");
usernameField.updateText(text);
if(k == 200 && selectedSlot > 0) {
--selectedSlot;
scrollPos = selectedSlot - 2;
}
if(k == 208 && selectedSlot < (dropDownOptions.length - 1)) {
++selectedSlot;
scrollPos = selectedSlot - 2;
}
}
protected void mouseClicked(int mx, int my, int button) {
super.mouseClicked(mx, my, button);
usernameField.mouseClicked(mx, my, button);
if (button == 0) {
if(newSkinWaitSteveOrAlex) {
int skinX = width / 2 - 90;
int skinY = height / 4;
int skinWidth = 70;
int skinHeight = 120;
if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) {
if(selectedSlot < EaglerProfile.customSkins.size()) {
newSkinWaitSteveOrAlex = false;
EaglerProfile.customSkins.get(selectedSlot).model = SkinModel.STEVE;
safeProfile();
}
return;
}
skinX = width / 2 + 20;
skinY = height / 4;
if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) {
if(selectedSlot < EaglerProfile.customSkins.size()) {
EaglerProfile.customSkins.get(selectedSlot).model = SkinModel.ALEX;
newSkinWaitSteveOrAlex = false;
safeProfile();
}
}
return;
}else if(selectedSlot < EaglerProfile.customSkins.size()) {
int skinX = width / 2 - 120;
int skinY = height / 6 + 18;
int skinWidth = 80;
int skinHeight = 120;
if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) {
if(selectedSlot < EaglerProfile.customSkins.size()) {
newSkinWaitSteveOrAlex = true;
return;
}
}
}
int skinX = width / 2 + 140 - 40;
int skinY = height / 6 + 82;
if(mx >= skinX && mx < (skinX + 20) && my >= skinY && my < (skinY + 22)) {
dropDownOpen = !dropDownOpen;
return;
}
skinX = width / 2 - 20;
skinY = height / 6 + 82;
int skinWidth = 140;
int skinHeight = skinsHeight;
if(!(mx >= skinX && mx < (skinX + skinWidth) && my >= skinY && my < (skinY + skinHeight + 22))) {
dropDownOpen = false;
dragging = false;
return;
}
skinY += 21;
if(dropDownOpen && !dragging) {
for(int i = 0; i < slotsVisible; i++) {
if(i + scrollPos < dropDownOptions.length) {
if(selectedSlot != i + scrollPos) {
if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15) && selectedSlot != i + scrollPos) {
selectedSlot = i + scrollPos;
dropDownOpen = false;
dragging = false;
}
}
}
}
}
}
}
protected void safeProfile() {
int customLen = EaglerProfile.customSkins.size();
if(selectedSlot < customLen) {
EaglerProfile.presetSkinId = -1;
EaglerProfile.customSkinId = selectedSlot;
}else {
EaglerProfile.presetSkinId = selectedSlot - customLen;
EaglerProfile.customSkinId = -1;
}
String name = usernameField.getText().trim();
while(name.length() < 3) {
name = name + "_";
}
if(name.length() > 16) {
name = name.substring(0, 16);
}
EaglerProfile.setName(name);
EaglerProfile.write();
}
}

View File

@ -0,0 +1,332 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
import net.lax1dude.eaglercraft.v1_8.mojang.authlib.TexturesProperty;
import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class ServerSkinCache {
private static final Logger logger = LogManager.getLogger("ServerSkinCache");
public class SkinCacheEntry {
protected final boolean isPresetSkin;
protected final int presetSkinId;
protected final CacheCustomSkin customSkin;
protected long lastCacheHit = System.currentTimeMillis();
protected SkinCacheEntry(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation, SkinModel model) {
this.isPresetSkin = false;
this.presetSkinId = -1;
this.customSkin = new CacheCustomSkin(textureInstance, resourceLocation, model);
ServerSkinCache.this.textureManager.loadTexture(resourceLocation, textureInstance);
}
/**
* Use only for the constant for the client player
*/
protected SkinCacheEntry(ResourceLocation resourceLocation, SkinModel model) {
this.isPresetSkin = false;
this.presetSkinId = -1;
this.customSkin = new CacheCustomSkin(null, resourceLocation, model);
}
protected SkinCacheEntry(int presetSkinId) {
this.isPresetSkin = true;
this.presetSkinId = presetSkinId;
this.customSkin = null;
}
public ResourceLocation getResourceLocation() {
if(isPresetSkin) {
return DefaultSkins.getSkinFromId(presetSkinId).location;
}else {
if(customSkin != null) {
return customSkin.resourceLocation;
}else {
return DefaultSkins.DEFAULT_STEVE.location;
}
}
}
public SkinModel getSkinModel() {
if(isPresetSkin) {
return DefaultSkins.getSkinFromId(presetSkinId).model;
}else {
if(customSkin != null) {
return customSkin.model;
}else {
return DefaultSkins.DEFAULT_STEVE.model;
}
}
}
protected void free() {
if(!isPresetSkin) {
ServerSkinCache.this.textureManager.deleteTexture(customSkin.resourceLocation);
}
}
}
protected static class CacheCustomSkin {
protected final EaglerSkinTexture textureInstance;
protected final ResourceLocation resourceLocation;
protected final SkinModel model;
protected CacheCustomSkin(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation, SkinModel model) {
this.textureInstance = textureInstance;
this.resourceLocation = resourceLocation;
this.model = model;
}
}
protected static class WaitingSkin {
protected final long timeout;
protected final SkinModel model;
protected WaitingSkin(long timeout, SkinModel model) {
this.timeout = timeout;
this.model = model;
}
}
private final SkinCacheEntry defaultCacheEntry = new SkinCacheEntry(0);
private final SkinCacheEntry defaultSlimCacheEntry = new SkinCacheEntry(1);
private final Map<EaglercraftUUID, SkinCacheEntry> skinsCache = new HashMap();
private final Map<EaglercraftUUID, WaitingSkin> waitingSkins = new HashMap();
private final Map<EaglercraftUUID, Long> evictedSkins = new HashMap();
private final EaglercraftNetworkManager networkManager;
protected final TextureManager textureManager;
private final EaglercraftUUID clientPlayerId;
private final SkinCacheEntry clientPlayerCacheEntry;
private long lastFlush = System.currentTimeMillis();
private long lastFlushReq = System.currentTimeMillis();
private long lastFlushEvict = System.currentTimeMillis();
private static int texId = 0;
public ServerSkinCache(EaglercraftNetworkManager networkManager, TextureManager textureManager) {
this.networkManager = networkManager;
this.textureManager = textureManager;
this.clientPlayerId = EaglerProfile.getPlayerUUID();
this.clientPlayerCacheEntry = new SkinCacheEntry(EaglerProfile.getActiveSkinResourceLocation(), EaglerProfile.getActiveSkinModel());
}
public SkinCacheEntry getClientPlayerSkin() {
return clientPlayerCacheEntry;
}
public SkinCacheEntry getSkin(GameProfile player) {
EaglercraftUUID uuid = player.getId();
if(uuid != null && uuid.equals(clientPlayerId)) {
return clientPlayerCacheEntry;
}
TexturesProperty props = player.getTextures();
if(props.eaglerPlayer || props.skin == null) {
if(uuid != null) {
return _getSkin(uuid);
}else {
if("slim".equalsIgnoreCase(props.model)) {
return defaultSlimCacheEntry;
}else {
return defaultCacheEntry;
}
}
}else {
return getSkin(props.skin, SkinModel.getModelFromId(props.model));
}
}
public SkinCacheEntry getSkin(EaglercraftUUID player) {
if(player.equals(clientPlayerId)) {
return clientPlayerCacheEntry;
}
return _getSkin(player);
}
private SkinCacheEntry _getSkin(EaglercraftUUID player) {
SkinCacheEntry etr = skinsCache.get(player);
if(etr == null) {
if(!waitingSkins.containsKey(player) && !evictedSkins.containsKey(player)) {
waitingSkins.put(player, new WaitingSkin(System.currentTimeMillis(), null));
PacketBuffer buffer;
try {
buffer = SkinPackets.writeGetOtherSkin(player);
}catch(IOException ex) {
logger.error("Could not write skin request packet!");
logger.error(ex);
return defaultCacheEntry;
}
networkManager.sendPacket(new C17PacketCustomPayload("EAG|Skins-1.8", buffer));
}
return defaultCacheEntry;
}else {
etr.lastCacheHit = System.currentTimeMillis();
return etr;
}
}
public SkinCacheEntry getSkin(String url, SkinModel skinModelResponse) {
if(url.length() > 0xFFFF) {
return skinModelResponse == SkinModel.ALEX ? defaultSlimCacheEntry : defaultCacheEntry;
}
EaglercraftUUID generatedUUID = SkinPackets.createEaglerURLSkinUUID(url);
SkinCacheEntry etr = skinsCache.get(generatedUUID);
if(etr != null) {
etr.lastCacheHit = System.currentTimeMillis();
return etr;
}else {
if(!waitingSkins.containsKey(generatedUUID) && !evictedSkins.containsKey(generatedUUID)) {
waitingSkins.put(generatedUUID, new WaitingSkin(System.currentTimeMillis(), skinModelResponse));
PacketBuffer buffer;
try {
buffer = SkinPackets.writeGetSkinByURL(generatedUUID, url);
}catch(IOException ex) {
logger.error("Could not write skin request packet!");
logger.error(ex);
return skinModelResponse == SkinModel.ALEX ? defaultSlimCacheEntry : defaultCacheEntry;
}
networkManager.sendPacket(new C17PacketCustomPayload("EAG|Skins-1.8", buffer));
}
}
return skinModelResponse == SkinModel.ALEX ? defaultSlimCacheEntry : defaultCacheEntry;
}
public void cacheSkinPreset(EaglercraftUUID player, int presetId) {
if(waitingSkins.remove(player) != null) {
SkinCacheEntry etr = skinsCache.remove(player);
if(etr != null) {
etr.free();
}
skinsCache.put(player, new SkinCacheEntry(presetId));
}else {
logger.error("Unsolicited skin response recieved for \"{}\"! (preset {})", player, presetId);
}
}
public void cacheSkinCustom(EaglercraftUUID player, byte[] pixels, SkinModel model) {
WaitingSkin waitingSkin;
if((waitingSkin = waitingSkins.remove(player)) != null) {
SkinCacheEntry etr = skinsCache.remove(player);
if(etr != null) {
etr.free();
}
if(waitingSkin.model != null) {
model = waitingSkin.model;
}else if(model == null) {
model = (player.hashCode() & 1) != 0 ? SkinModel.ALEX : SkinModel.STEVE;
}
try {
etr = new SkinCacheEntry(new EaglerSkinTexture(pixels, model.width, model.height),
new ResourceLocation("eagler:skins/multiplayer/tex_" + texId++), model);
}catch(Throwable t) {
etr = new SkinCacheEntry(0);
logger.error("Could not process custom skin packet for \"{}\"!", player);
logger.error(t);
}
skinsCache.put(player, etr);
}else {
logger.error("Unsolicited skin response recieved for \"{}\"! (custom {}x{})", player, model.width, model.height);
}
}
public SkinModel getRequestedSkinType(EaglercraftUUID waiting) {
WaitingSkin waitingSkin;
if((waitingSkin = waitingSkins.get(waiting)) != null) {
return waitingSkin.model;
}else {
return null;
}
}
public void flush() {
long millis = System.currentTimeMillis();
if(millis - lastFlushReq > 5000l) {
lastFlushReq = millis;
if(!waitingSkins.isEmpty()) {
Iterator<WaitingSkin> waitingItr = waitingSkins.values().iterator();
while(waitingItr.hasNext()) {
if(millis - waitingItr.next().timeout > 30000l) {
waitingItr.remove();
}
}
}
}
if(millis - lastFlushEvict > 1000l) {
lastFlushEvict = millis;
if(!evictedSkins.isEmpty()) {
Iterator<Long> evictItr = evictedSkins.values().iterator();
while(evictItr.hasNext()) {
if(millis - evictItr.next().longValue() > 3000l) {
evictItr.remove();
}
}
}
}
if(millis - lastFlush > 60000l) {
lastFlush = millis;
if(!skinsCache.isEmpty()) {
Iterator<SkinCacheEntry> entryItr = skinsCache.values().iterator();
while(entryItr.hasNext()) {
SkinCacheEntry etr = entryItr.next();
if(millis - etr.lastCacheHit > 900000l) { // 15 minutes
entryItr.remove();
etr.free();
}
}
}
}
}
public void destroy() {
Iterator<SkinCacheEntry> entryItr = skinsCache.values().iterator();
while(entryItr.hasNext()) {
entryItr.next().free();
}
skinsCache.clear();
waitingSkins.clear();
}
public void evictSkin(EaglercraftUUID uuid) {
evictedSkins.put(uuid, Long.valueOf(System.currentTimeMillis()));
SkinCacheEntry etr = skinsCache.remove(uuid);
if(etr != null) {
etr.free();
}
}
}

View File

@ -0,0 +1,61 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class SkinConverter {
public static void convert64x32to64x64(ImageData skinIn, ImageData skinOut) {
copyRawPixels(skinIn.pixels, skinOut.pixels, 0, 0, 0, 0, 64, 32, 64, 64, false);
copyRawPixels(skinIn.pixels, skinOut.pixels, 24, 48, 20, 52, 4, 16, 8, 20, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 28, 48, 24, 52, 8, 16, 12, 20, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 20, 52, 16, 64, 8, 20, 12, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 24, 52, 20, 64, 4, 20, 8, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 28, 52, 24, 64, 0, 20, 4, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 32, 52, 28, 64, 12, 20, 16, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 40, 48, 36, 52, 44, 16, 48, 20, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 44, 48, 40, 52, 48, 16, 52, 20, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 36, 52, 32, 64, 48, 20, 52, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 40, 52, 36, 64, 44, 20, 48, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 44, 52, 40, 64, 40, 20, 44, 32, 64, 64);
copyRawPixels(skinIn.pixels, skinOut.pixels, 48, 52, 44, 64, 52, 20, 56, 32, 64, 64);
}
private static void copyRawPixels(int[] imageIn, int[] imageOut, int dx1, int dy1, int dx2, int dy2, int sx1,
int sy1, int sx2, int sy2, int imgSrcWidth, int imgDstWidth) {
if(dx1 > dx2) {
copyRawPixels(imageIn, imageOut, sx1, sy1, dx2, dy1, sx2 - sx1, sy2 - sy1, imgSrcWidth, imgDstWidth, true);
} else {
copyRawPixels(imageIn, imageOut, sx1, sy1, dx1, dy1, sx2 - sx1, sy2 - sy1, imgSrcWidth, imgDstWidth, false);
}
}
private static void copyRawPixels(int[] imageIn, int[] imageOut, int srcX, int srcY, int dstX, int dstY, int width,
int height, int imgSrcWidth, int imgDstWidth, boolean flip) {
int i, j;
for(int y = 0; y < height; ++y) {
for(int x = 0; x < width; ++x) {
i = imageIn[(srcY + y) * imgSrcWidth + srcX + x];
if(flip) {
j = (dstY + y) * imgDstWidth + dstX + width - x - 1;
}else {
j = (dstY + y) * imgDstWidth + dstX + x;
}
imageOut[j] = i;
}
}
}
}

View File

@ -0,0 +1,67 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.util.HashMap;
import java.util.Map;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public enum SkinModel {
STEVE(0, 64, 64, "default", false), ALEX(1, 64, 64, "slim", false), ZOMBIE(2, 64, 64, "zombie", true);
public final int id;
public final int width;
public final int height;
public final String profileSkinType;
public final boolean sanitize;
public static final SkinModel[] skinModels = new SkinModel[3];
private static final Map<String, SkinModel> skinModelsByName = new HashMap();
private SkinModel(int id, int w, int h, String profileSkinType, boolean sanitize) {
this.id = id;
this.width = w;
this.height = h;
this.profileSkinType = profileSkinType;
this.sanitize = sanitize;
}
public static SkinModel getModelFromId(String str) {
SkinModel mdl = skinModelsByName.get(str.toLowerCase());
if(mdl == null) {
return skinModels[0];
}
return mdl;
}
public static SkinModel getModelFromId(int id) {
SkinModel s = null;
if(id >= 0 && id < skinModels.length) {
s = skinModels[id];
}
if(s != null) {
return s;
}else {
return STEVE;
}
}
static {
SkinModel[] arr = values();
for(int i = 0; i < arr.length; ++i) {
skinModels[arr[i].id] = arr[i];
skinModelsByName.put(arr[i].profileSkinType, arr[i]);
}
}
}

View File

@ -0,0 +1,121 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.ArrayUtils;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.crypto.MD5Digest;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.network.PacketBuffer;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class SkinPackets {
public static final int PACKET_MY_SKIN_PRESET = 0x01;
public static final int PACKET_MY_SKIN_CUSTOM = 0x02;
public static final int PACKET_GET_OTHER_SKIN = 0x03;
public static final int PACKET_OTHER_SKIN_PRESET = 0x04;
public static final int PACKET_OTHER_SKIN_CUSTOM = 0x05;
public static final int PACKET_GET_SKIN_BY_URL = 0x06;
public static void readPluginMessage(PacketBuffer buffer, ServerSkinCache skinCache) throws IOException {
try {
int type = (int)buffer.readByte() & 0xFF;
switch(type) {
case PACKET_OTHER_SKIN_PRESET: {
EaglercraftUUID responseUUID = buffer.readUuid();
int responsePreset = buffer.readInt();
if(buffer.isReadable()) {
throw new IOException("PACKET_OTHER_SKIN_PRESET had " + buffer.readableBytes() + " remaining bytes!");
}
skinCache.cacheSkinPreset(responseUUID, responsePreset);
break;
}
case PACKET_OTHER_SKIN_CUSTOM: {
EaglercraftUUID responseUUID = buffer.readUuid();
int model = (int)buffer.readByte() & 0xFF;
SkinModel modelId;
if(model == (byte)0xFF) {
modelId = skinCache.getRequestedSkinType(responseUUID);
}else {
modelId = SkinModel.getModelFromId(model & 0x7F);
if((model & 0x80) != 0 && modelId.sanitize) {
modelId = SkinModel.STEVE;
}
}
int bytesToRead = modelId.width * modelId.height * 4;
byte[] readSkin = new byte[bytesToRead];
buffer.readBytes(readSkin);
if(buffer.isReadable()) {
throw new IOException("PACKET_MY_SKIN_CUSTOM had " + buffer.readableBytes() + " remaining bytes!");
}
skinCache.cacheSkinCustom(responseUUID, readSkin, modelId);
break;
}
default:
throw new IOException("Unknown skin packet type: " + type);
}
}catch(IOException ex) {
throw ex;
}catch(Throwable t) {
throw new IOException("Failed to parse skin packet!", t);
}
}
public static byte[] writeMySkinPreset(int skinId) throws IOException {
return new byte[] { (byte) PACKET_MY_SKIN_PRESET, (byte) (skinId >> 24), (byte) (skinId >> 16),
(byte) (skinId >> 8), (byte) (skinId & 0xFF) };
}
public static byte[] writeMySkinCustom(CustomSkin customSkin) throws IOException {
byte[] packet = new byte[2 + customSkin.texture.length];
packet[0] = (byte) PACKET_MY_SKIN_CUSTOM;
packet[1] = (byte) customSkin.model.id;
System.arraycopy(customSkin.texture, 0, packet, 2, customSkin.texture.length);
return packet;
}
public static PacketBuffer writeGetOtherSkin(EaglercraftUUID skinId) throws IOException {
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17));
ret.writeByte(PACKET_GET_OTHER_SKIN);
ret.writeUuid(skinId);
return ret;
}
public static PacketBuffer writeGetSkinByURL(EaglercraftUUID skinId, String skinUrl) throws IOException {
int len = 19 + skinUrl.length();
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(len, len));
ret.writeByte(PACKET_GET_SKIN_BY_URL);
ret.writeUuid(skinId);
byte[] url = ArrayUtils.asciiString(skinUrl);
ret.writeShort((int)url.length);
ret.writeBytes(url);
return ret;
}
public static EaglercraftUUID createEaglerURLSkinUUID(String skinUrl){
MD5Digest dg = new MD5Digest();
byte[] bytes = ArrayUtils.asciiString("EaglercraftSkinURL:" + skinUrl);
dg.update(bytes, 0, bytes.length);
byte[] md5Bytes = new byte[16];
dg.doFinal(md5Bytes, 0);
md5Bytes[6] &= 0x0f;
md5Bytes[6] |= 0x30;
md5Bytes[8] &= 0x3f;
md5Bytes[8] |= 0x80;
return new EaglercraftUUID(md5Bytes);
}
}

View File

@ -0,0 +1,76 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelPlayer;
import net.minecraft.client.model.ModelZombie;
import net.minecraft.client.renderer.RenderHelper;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class SkinPreviewRenderer {
private static ModelPlayer playerModelSteve = null;
private static ModelPlayer playerModelAlex = null;
private static ModelZombie playerModelZombie = null;
public static void initialize() {
playerModelSteve = new ModelPlayer(0.0f, false);
playerModelSteve.isChild = false;
playerModelAlex = new ModelPlayer(0.0f, true);
playerModelAlex.isChild = false;
playerModelZombie = new ModelZombie(0.0f, true);
playerModelZombie.isChild = false;
}
public static void renderBiped(int x, int y, int mx, int my, SkinModel skinModel) {
ModelBiped model;
switch(skinModel) {
case STEVE:
default:
model = playerModelSteve;
break;
case ALEX:
model = playerModelAlex;
break;
case ZOMBIE:
model = playerModelZombie;
break;
}
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
GlStateManager.disableCull();
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
GlStateManager.pushMatrix();
GlStateManager.translate(x, y - 80.0f, 100.0f);
GlStateManager.scale(50.0f, 50.0f, 50.0f);
GlStateManager.rotate(180.0f, 1.0f, 0.0f, 0.0f);
GlStateManager.scale(1.0f, -1.0f, 1.0f);
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.translate(0.0f, 1.0f, 0.0f);
GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f);
GlStateManager.rotate(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f);
GlStateManager.translate(0.0f, -1.0f, 0.0f);
model.render(null, 0.0f, 0.0f, (float)(System.currentTimeMillis() % 2000000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625f);
GlStateManager.popMatrix();
GlStateManager.disableLighting();
}
}