Update #37 - Touch support without userscript, many other feats

This commit is contained in:
lax1dude
2024-09-21 20:17:42 -07:00
parent 173727c8c4
commit ec1ab8ece3
683 changed files with 62074 additions and 8996 deletions

View File

@ -1,11 +1,5 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.network.PacketBuffer;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
@ -25,42 +19,6 @@ public class CapePackets {
public static final int PACKET_MY_CAPE_PRESET = 0x01;
public static final int PACKET_MY_CAPE_CUSTOM = 0x02;
public static final int PACKET_GET_OTHER_CAPE = 0x03;
public static final int PACKET_OTHER_CAPE_PRESET = 0x04;
public static final int PACKET_OTHER_CAPE_CUSTOM = 0x05;
public static void readPluginMessage(PacketBuffer buffer, ServerCapeCache capeCache) throws IOException {
try {
int type = (int)buffer.readByte() & 0xFF;
switch(type) {
case PACKET_OTHER_CAPE_PRESET: {
EaglercraftUUID responseUUID = buffer.readUuid();
int responsePreset = buffer.readInt();
if(buffer.isReadable()) {
throw new IOException("PACKET_OTHER_CAPE_PRESET had " + buffer.readableBytes() + " remaining bytes!");
}
capeCache.cacheCapePreset(responseUUID, responsePreset);
break;
}
case PACKET_OTHER_CAPE_CUSTOM: {
EaglercraftUUID responseUUID = buffer.readUuid();
byte[] readCape = new byte[1173];
buffer.readBytes(readCape);
if(buffer.isReadable()) {
throw new IOException("PACKET_OTHER_CAPE_CUSTOM had " + buffer.readableBytes() + " remaining bytes!");
}
capeCache.cacheCapeCustom(responseUUID, readCape);
break;
}
default:
throw new IOException("Unknown skin packet type: " + type);
}
}catch(IOException ex) {
throw ex;
}catch(Throwable t) {
throw new IOException("Failed to parse cape packet!", t);
}
}
public static byte[] writeMyCapePreset(int capeId) {
return new byte[] { (byte) PACKET_MY_CAPE_PRESET, (byte) (capeId >>> 24), (byte) (capeId >>> 16),
@ -74,10 +32,4 @@ public class CapePackets {
return packet;
}
public static PacketBuffer writeGetOtherCape(EaglercraftUUID playerId) throws IOException {
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17));
ret.writeByte(PACKET_GET_OTHER_CAPE);
ret.writeUuid(playerId);
return ret;
}
}

View File

@ -40,12 +40,34 @@ public class EaglerProfile {
public static int presetCapeId;
public static int customCapeId;
public static final List<CustomSkin> customSkins = new ArrayList();
public static final List<CustomCape> customCapes = new ArrayList();
public static boolean isServerSkinOverride = false;
public static int overridePresetSkinId = -1;
public static final ResourceLocation overrideCustomSkinTexture = new ResourceLocation("eagler:skins/custom/tex_server_override");
public static EaglerSkinTexture overrideCustomSkin = null;
public static SkinModel overrideCustomSkinModel = SkinModel.STEVE;
public static boolean isServerCapeOverride = false;
public static int overridePresetCapeId = -1;
public static final ResourceLocation overrideCustomCapeTexture = new ResourceLocation("eagler:capes/custom/tex_server_override");
public static EaglerSkinTexture overrideCustomCape = null;
public static final List<CustomSkin> customSkins = new ArrayList<>();
public static final List<CustomCape> customCapes = new ArrayList<>();
public static final EaglercraftRandom rand;
public static ResourceLocation getActiveSkinResourceLocation() {
if(isServerSkinOverride) {
if(overridePresetSkinId == -1) {
return overrideCustomSkinTexture;
}else {
if(overridePresetSkinId >= 0 && overridePresetSkinId < DefaultSkins.defaultSkinsMap.length) {
return DefaultSkins.defaultSkinsMap[overridePresetSkinId].location;
}else {
return DefaultSkins.defaultSkinsMap[0].location;
}
}
}
if(presetSkinId == -1) {
if(customSkinId >= 0 && customSkinId < customSkins.size()) {
return customSkins.get(customSkinId).getResource();
@ -65,6 +87,17 @@ public class EaglerProfile {
}
public static SkinModel getActiveSkinModel() {
if(isServerSkinOverride) {
if(overridePresetSkinId == -1) {
return overrideCustomSkinModel;
}else {
if(overridePresetSkinId >= 0 && overridePresetSkinId < DefaultSkins.defaultSkinsMap.length) {
return DefaultSkins.defaultSkinsMap[overridePresetSkinId].model;
}else {
return DefaultSkins.defaultSkinsMap[0].model;
}
}
}
if(presetSkinId == -1) {
if(customSkinId >= 0 && customSkinId < customSkins.size()) {
return customSkins.get(customSkinId).model;
@ -84,6 +117,17 @@ public class EaglerProfile {
}
public static ResourceLocation getActiveCapeResourceLocation() {
if(isServerCapeOverride) {
if(overridePresetCapeId == -1) {
return overrideCustomCapeTexture;
}else {
if(overridePresetCapeId >= 0 && overridePresetCapeId < DefaultCapes.defaultCapesMap.length) {
return DefaultCapes.defaultCapesMap[overridePresetCapeId].location;
}else {
return DefaultCapes.defaultCapesMap[0].location;
}
}
}
if(presetCapeId == -1) {
if(customCapeId >= 0 && customCapeId < customCapes.size()) {
return customCapes.get(customCapeId).getResource();
@ -118,10 +162,15 @@ public class EaglerProfile {
}
}
public static byte[] getSkinPacket() {
public static byte[] getSkinPacket(int vers) {
if(presetSkinId == -1) {
if(customSkinId >= 0 && customSkinId < customSkins.size()) {
return SkinPackets.writeMySkinCustom(customSkins.get(customSkinId));
CustomSkin toSend = customSkins.get(customSkinId);
if(vers <= 3) {
return SkinPackets.writeMySkinCustomV3(toSend);
}else {
return SkinPackets.writeMySkinCustomV4(toSend);
}
}else {
customSkinId = -1;
presetSkinId = 0;
@ -156,6 +205,59 @@ public class EaglerProfile {
}
}
public static void handleForceSkinPreset(int preset) {
isServerSkinOverride = true;
overridePresetSkinId = preset;
ServerSkinCache.needReloadClientSkin = true;
}
public static void handleForceSkinCustom(int modelID, byte[] datav3) {
if(datav3.length != 16384) {
return;
}
isServerSkinOverride = true;
overridePresetSkinId = -1;
overrideCustomSkinModel = SkinModel.getModelFromId(modelID);
if(overrideCustomSkinModel.highPoly != null) {
overrideCustomSkinModel = SkinModel.STEVE;
}
if(overrideCustomSkin == null) {
overrideCustomSkin = new EaglerSkinTexture(datav3, 64, 64);
Minecraft.getMinecraft().getTextureManager().loadTexture(overrideCustomSkinTexture, overrideCustomSkin);
}else {
overrideCustomSkin.copyPixelsIn(datav3);
}
ServerSkinCache.needReloadClientSkin = true;
}
public static void handleForceCapePreset(int preset) {
isServerCapeOverride = true;
overridePresetCapeId = preset;
ServerCapeCache.needReloadClientCape = true;
}
public static void handleForceCapeCustom(byte[] custom) {
if(custom.length != 1173) {
return;
}
byte[] pixels32x32 = new byte[4096];
SkinConverter.convertCape23x17RGBto32x32RGBA(custom, pixels32x32);
isServerCapeOverride = true;
overridePresetCapeId = -1;
if(overrideCustomCape == null) {
overrideCustomCape = new EaglerSkinTexture(pixels32x32, 32, 32);
Minecraft.getMinecraft().getTextureManager().loadTexture(overrideCustomCapeTexture, overrideCustomCape);
}else {
overrideCustomCape.copyPixelsIn(pixels32x32);
}
ServerCapeCache.needReloadClientCape = true;
}
public static void clearServerSkinOverride() {
isServerSkinOverride = false;
isServerCapeOverride = false;
}
private static boolean doesSkinExist(String name) {
for(int i = 0, l = customSkins.size(); i < l; ++i) {
if(customSkins.get(i).name.equalsIgnoreCase(name)) {

View File

@ -44,15 +44,23 @@ public class EaglerSkinTexture implements ITextureObject {
if(pixels.length != width * height * 4) {
throw new IllegalArgumentException("Wrong data length " + pixels.length + " for " + width + "x" + height + " texture");
}
this.pixels = convertToInt(pixels);
this.width = width;
this.height = height;
}
public static int[] convertToInt(byte[] pixels) {
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;
return p;
}
public void copyPixelsIn(byte[] pixels) {
copyPixelsIn(convertToInt(pixels));
}
public void copyPixelsIn(int[] pixels) {
@ -93,4 +101,16 @@ public class EaglerSkinTexture implements ITextureObject {
textureId = -1;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int[] getData() {
return pixels;
}
}

View File

@ -2,7 +2,7 @@ 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.minecraft.EnumInputEvent;
import net.lax1dude.eaglercraft.v1_8.socket.ConnectionHandshake;
import net.lax1dude.eaglercraft.v1_8.socket.HandshakePacketTypes;
import net.minecraft.client.gui.GuiButton;
@ -92,9 +92,6 @@ public class GuiAuthenticationScreen extends GuiScreen {
this.mc.displayGuiScreen(new GuiConnecting(retAfterAuthScreen, password.getText()));
}else {
this.mc.displayGuiScreen(parent);
if (!PlatformNetworking.playConnectionState().isClosed()) {
PlatformNetworking.playDisconnect();
}
}
}
@ -122,4 +119,14 @@ public class GuiAuthenticationScreen extends GuiScreen {
this.password.mouseClicked(parInt1, parInt2, parInt3);
}
@Override
public boolean showCopyPasteButtons() {
return password.isFocused();
}
@Override
public void fireInputEvent(EnumInputEvent event, String param) {
password.fireInputEvent(event, param);
}
}

View File

@ -3,6 +3,7 @@ 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.PointerInputAbstraction;
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
@ -51,7 +52,6 @@ public class GuiScreenEditCape extends GuiScreen {
public GuiScreenEditCape(GuiScreenEditProfile parent) {
this.parent = parent;
updateOptions();
}
public void initGui() {
@ -61,6 +61,7 @@ public class GuiScreenEditCape extends GuiScreen {
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 + 80, 71, 20, I18n.format("editCape.addCape")));
buttonList.add(new GuiButton(2, width / 2 - 21 + 71, height / 6 + 80, 72, 20, I18n.format("editCape.clearCape")));
updateOptions();
}
private void updateOptions() {
@ -243,7 +244,7 @@ public class GuiScreenEditCape extends GuiScreen {
if(EagRuntime.fileChooserHasResult()) {
FileChooserResult result = EagRuntime.getFileChooserResult();
if(result != null) {
ImageData loadedCape = ImageData.loadImageFile(result.fileData);
ImageData loadedCape = ImageData.loadImageFile(result.fileData, ImageData.getMimeFromType(result.fileName));
if(loadedCape != null) {
if((loadedCape.width == 32 || loadedCape.width == 64) && loadedCape.height == 32) {
byte[] resized = new byte[1173];
@ -258,12 +259,12 @@ public class GuiScreenEditCape extends GuiScreen {
EagRuntime.showPopup("The selected image '" + result.fileName + "' is not the right size!\nEaglercraft only supports 32x32 or 64x32 capes");
}
}else {
EagRuntime.showPopup("The selected file '" + result.fileName + "' is not a PNG file!");
EagRuntime.showPopup("The selected file '" + result.fileName + "' is not a supported format!");
}
}
}
if(dropDownOpen) {
if(Mouse.isButtonDown(0)) {
if(PointerInputAbstraction.getVCursorButtonDown(0)) {
int skinX = width / 2 - 20;
int skinY = height / 6 + 73;
int skinWidth = 140;

View File

@ -3,8 +3,10 @@ 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.PointerInputAbstraction;
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
import net.lax1dude.eaglercraft.v1_8.minecraft.EnumInputEvent;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
import net.minecraft.client.audio.PositionedSoundRecord;
@ -57,7 +59,6 @@ public class GuiScreenEditProfile extends GuiScreen {
public GuiScreenEditProfile(GuiScreen parent) {
this.parent = parent;
updateOptions();
}
public void initGui() {
@ -66,10 +67,12 @@ public class GuiScreenEditProfile extends GuiScreen {
usernameField = new GuiTextField(0, fontRendererObj, width / 2 - 20 + 1, height / 6 + 24 + 1, 138, 20);
usernameField.setFocused(true);
usernameField.setText(EaglerProfile.getName());
usernameField.setMaxStringLength(16);
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")));
updateOptions();
}
private void updateOptions() {
@ -330,7 +333,7 @@ public class GuiScreenEditProfile extends GuiScreen {
if(EagRuntime.fileChooserHasResult()) {
FileChooserResult result = EagRuntime.getFileChooserResult();
if(result != null) {
ImageData loadedSkin = ImageData.loadImageFile(result.fileData);
ImageData loadedSkin = ImageData.loadImageFile(result.fileData, ImageData.getMimeFromType(result.fileName));
if(loadedSkin != null) {
boolean isLegacy = loadedSkin.width == 64 && loadedSkin.height == 32;
boolean isModern = loadedSkin.width == 64 && loadedSkin.height == 64;
@ -367,12 +370,12 @@ public class GuiScreenEditProfile extends GuiScreen {
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!");
EagRuntime.showPopup("The selected file '" + result.fileName + "' is not a supported format!");
}
}
}
if(dropDownOpen) {
if(Mouse.isButtonDown(0)) {
if(PointerInputAbstraction.getVCursorButtonDown(0)) {
int skinX = width / 2 - 20;
int skinY = height / 6 + 103;
int skinWidth = 140;
@ -532,4 +535,14 @@ public class GuiScreenEditProfile extends GuiScreen {
EaglerProfile.setName(name);
}
@Override
public boolean showCopyPasteButtons() {
return usernameField.isFocused();
}
@Override
public void fireInputEvent(EnumInputEvent event, String param) {
usernameField.fireInputEvent(event, param);
}
}

View File

@ -77,8 +77,8 @@ public class GuiScreenImportProfile extends GuiScreen {
}else {
mc.loadingScreen.eaglerShow(I18n.format("settingsBackup.importing.1"), I18n.format("settingsBackup.importing.2"));
try {
List<String> list1 = new ArrayList(mc.gameSettings.resourcePacks);
List<String> list2 = new ArrayList(mc.gameSettings.field_183018_l);
List<String> list1 = new ArrayList<>(mc.gameSettings.resourcePacks);
List<String> list2 = new ArrayList<>(mc.gameSettings.field_183018_l);
importer.importProfileAndSettings(doImportProfile, doImportSettings, doImportServers, doImportResourcePacks);
boolean resourcePacksChanged = !mc.gameSettings.resourcePacks.equals(list1) || !mc.gameSettings.field_183018_l.equals(list2);
if(resourcePacksChanged || (doImportResourcePacks && (list1.size() > 0 || list2.size() > 0))) {

View File

@ -2,6 +2,7 @@ package net.lax1dude.eaglercraft.v1_8.profile;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader;
@ -158,7 +159,7 @@ public class RenderHighPoly extends RenderPlayer {
if(highPolySkin.headModel != null) {
if(highPolySkin == HighPolySkin.BABY_CHARLES) {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
float partialTicks = (float) ((millis - abstractclientplayer.eaglerHighPolyAnimationTick) * 0.02);
//long l50 = millis / 50l * 50l;
//boolean runTick = par1EntityPlayer.eaglerHighPolyAnimationTick < l50 && millis >= l50;

View File

@ -1,17 +1,16 @@
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.EagRuntime;
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.socket.EaglercraftNetworkManager;
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.CPacketGetOtherCapeEAG;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.util.ResourceLocation;
/**
@ -39,7 +38,7 @@ public class ServerCapeCache {
protected final int presetCapeId;
protected final CacheCustomCape customCape;
protected long lastCacheHit = System.currentTimeMillis();
protected long lastCacheHit = EagRuntime.steadyTimeMillis();
protected CapeCacheEntry(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation) {
this.isPresetCape = false;
@ -96,26 +95,32 @@ public class ServerCapeCache {
}
private final CapeCacheEntry defaultCacheEntry = new CapeCacheEntry(0);
private final Map<EaglercraftUUID, CapeCacheEntry> capesCache = new HashMap();
private final Map<EaglercraftUUID, Long> waitingCapes = new HashMap();
private final Map<EaglercraftUUID, Long> evictedCapes = new HashMap();
private final Map<EaglercraftUUID, CapeCacheEntry> capesCache = new HashMap<>();
private final Map<EaglercraftUUID, Long> waitingCapes = new HashMap<>();
private final Map<EaglercraftUUID, Long> evictedCapes = new HashMap<>();
private final EaglercraftNetworkManager networkManager;
private final NetHandlerPlayClient netHandler;
protected final TextureManager textureManager;
private final EaglercraftUUID clientPlayerId;
private final CapeCacheEntry clientPlayerCacheEntry;
private CapeCacheEntry clientPlayerCacheEntry;
private long lastFlush = System.currentTimeMillis();
private long lastFlushReq = System.currentTimeMillis();
private long lastFlushEvict = System.currentTimeMillis();
private long lastFlush = EagRuntime.steadyTimeMillis();
private long lastFlushReq = EagRuntime.steadyTimeMillis();
private long lastFlushEvict = EagRuntime.steadyTimeMillis();
private static int texId = 0;
public static boolean needReloadClientCape = false;
public ServerCapeCache(EaglercraftNetworkManager networkManager, TextureManager textureManager) {
this.networkManager = networkManager;
public ServerCapeCache(NetHandlerPlayClient netHandler, TextureManager textureManager) {
this.netHandler = netHandler;
this.textureManager = textureManager;
this.clientPlayerId = EaglerProfile.getPlayerUUID();
reloadClientPlayerCape();
}
public void reloadClientPlayerCape() {
needReloadClientCape = false;
this.clientPlayerCacheEntry = new CapeCacheEntry(EaglerProfile.getActiveCapeResourceLocation());
}
@ -130,20 +135,12 @@ public class ServerCapeCache {
CapeCacheEntry etr = capesCache.get(player);
if(etr == null) {
if(!waitingCapes.containsKey(player) && !evictedCapes.containsKey(player)) {
waitingCapes.put(player, System.currentTimeMillis());
PacketBuffer buffer;
try {
buffer = CapePackets.writeGetOtherCape(player);
}catch(IOException ex) {
logger.error("Could not write cape request packet!");
logger.error(ex);
return defaultCacheEntry;
}
networkManager.sendPacket(new C17PacketCustomPayload("EAG|Capes-1.8", buffer));
waitingCapes.put(player, EagRuntime.steadyTimeMillis());
netHandler.sendEaglerMessage(new CPacketGetOtherCapeEAG(player.msb, player.lsb));
}
return defaultCacheEntry;
}else {
etr.lastCacheHit = System.currentTimeMillis();
etr.lastCacheHit = EagRuntime.steadyTimeMillis();
return etr;
}
}
@ -183,7 +180,7 @@ public class ServerCapeCache {
}
public void flush() {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
if(millis - lastFlushReq > 5000l) {
lastFlushReq = millis;
if(!waitingCapes.isEmpty()) {
@ -219,6 +216,9 @@ public class ServerCapeCache {
}
}
}
if(needReloadClientCape) {
reloadClientPlayerCape();
}
}
public void destroy() {
@ -232,7 +232,14 @@ public class ServerCapeCache {
}
public void evictCape(EaglercraftUUID uuid) {
evictedCapes.put(uuid, Long.valueOf(System.currentTimeMillis()));
evictedCapes.put(uuid, Long.valueOf(EagRuntime.steadyTimeMillis()));
CapeCacheEntry etr = capesCache.remove(uuid);
if(etr != null) {
etr.free();
}
}
public void handleInvalidate(EaglercraftUUID uuid) {
CapeCacheEntry etr = capesCache.remove(uuid);
if(etr != null) {
etr.free();

View File

@ -1,19 +1,19 @@
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.EagRuntime;
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.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.CPacketGetOtherSkinEAG;
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.CPacketGetSkinByURLEAG;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.util.ResourceLocation;
/**
@ -41,7 +41,7 @@ public class ServerSkinCache {
protected final int presetSkinId;
protected final CacheCustomSkin customSkin;
protected long lastCacheHit = System.currentTimeMillis();
protected long lastCacheHit = EagRuntime.steadyTimeMillis();
protected SkinCacheEntry(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation, SkinModel model) {
this.isPresetSkin = false;
@ -125,26 +125,32 @@ public class ServerSkinCache {
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 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;
private final NetHandlerPlayClient netHandler;
protected final TextureManager textureManager;
private final EaglercraftUUID clientPlayerId;
private final SkinCacheEntry clientPlayerCacheEntry;
private SkinCacheEntry clientPlayerCacheEntry;
private long lastFlush = System.currentTimeMillis();
private long lastFlushReq = System.currentTimeMillis();
private long lastFlushEvict = System.currentTimeMillis();
private long lastFlush = EagRuntime.steadyTimeMillis();
private long lastFlushReq = EagRuntime.steadyTimeMillis();
private long lastFlushEvict = EagRuntime.steadyTimeMillis();
private static int texId = 0;
public static boolean needReloadClientSkin = false;
public ServerSkinCache(EaglercraftNetworkManager networkManager, TextureManager textureManager) {
this.networkManager = networkManager;
public ServerSkinCache(NetHandlerPlayClient netHandler, TextureManager textureManager) {
this.netHandler = netHandler;
this.textureManager = textureManager;
this.clientPlayerId = EaglerProfile.getPlayerUUID();
reloadClientPlayerSkin();
}
public void reloadClientPlayerSkin() {
needReloadClientSkin = false;
this.clientPlayerCacheEntry = new SkinCacheEntry(EaglerProfile.getActiveSkinResourceLocation(), EaglerProfile.getActiveSkinModel());
}
@ -184,20 +190,12 @@ public class ServerSkinCache {
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));
waitingSkins.put(player, new WaitingSkin(EagRuntime.steadyTimeMillis(), null));
netHandler.sendEaglerMessage(new CPacketGetOtherSkinEAG(player.msb, player.lsb));
}
return defaultCacheEntry;
}else {
etr.lastCacheHit = System.currentTimeMillis();
etr.lastCacheHit = EagRuntime.steadyTimeMillis();
return etr;
}
}
@ -209,20 +207,12 @@ public class ServerSkinCache {
EaglercraftUUID generatedUUID = SkinPackets.createEaglerURLSkinUUID(url);
SkinCacheEntry etr = skinsCache.get(generatedUUID);
if(etr != null) {
etr.lastCacheHit = System.currentTimeMillis();
etr.lastCacheHit = EagRuntime.steadyTimeMillis();
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));
waitingSkins.put(generatedUUID, new WaitingSkin(EagRuntime.steadyTimeMillis(), skinModelResponse));
netHandler.sendEaglerMessage(new CPacketGetSkinByURLEAG(generatedUUID.msb, generatedUUID.lsb, url));
}
}
return skinModelResponse == SkinModel.ALEX ? defaultSlimCacheEntry : defaultCacheEntry;
@ -276,13 +266,13 @@ public class ServerSkinCache {
}
public void flush() {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
if(millis - lastFlushReq > 5000l) {
lastFlushReq = millis;
if(!waitingSkins.isEmpty()) {
Iterator<WaitingSkin> waitingItr = waitingSkins.values().iterator();
while(waitingItr.hasNext()) {
if(millis - waitingItr.next().timeout > 30000l) {
if(millis - waitingItr.next().timeout > 20000l) {
waitingItr.remove();
}
}
@ -312,6 +302,9 @@ public class ServerSkinCache {
}
}
}
if(needReloadClientSkin) {
reloadClientPlayerSkin();
}
}
public void destroy() {
@ -325,7 +318,14 @@ public class ServerSkinCache {
}
public void evictSkin(EaglercraftUUID uuid) {
evictedSkins.put(uuid, Long.valueOf(System.currentTimeMillis()));
evictedSkins.put(uuid, Long.valueOf(EagRuntime.steadyTimeMillis()));
SkinCacheEntry etr = skinsCache.remove(uuid);
if(etr != null) {
etr.free();
}
}
public void handleInvalidate(EaglercraftUUID uuid) {
SkinCacheEntry etr = skinsCache.remove(uuid);
if(etr != null) {
etr.free();

View File

@ -32,7 +32,7 @@ public enum SkinModel {
public final HighPolySkin highPoly;
public static final SkinModel[] skinModels = new SkinModel[8];
private static final Map<String, SkinModel> skinModelsByName = new HashMap();
private static final Map<String, SkinModel> skinModelsByName = new HashMap<>();
private SkinModel(int id, int w, int h, String profileSkinType, boolean sanitize) {
this.id = id;

View File

@ -1,12 +1,8 @@
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-2023 lax1dude, ayunami2000. All Rights Reserved.
@ -27,97 +23,33 @@ 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 final int PACKET_INSTALL_NEW_SKIN = 0x07;
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;
}
}
if(modelId.highPoly != null) {
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) {
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) {
byte[] packet = new byte[2 + customSkin.texture.length];
public static byte[] writeMySkinCustomV3(CustomSkin customSkin) {
byte[] packet = new byte[2 + 16384];
packet[0] = (byte) PACKET_MY_SKIN_CUSTOM;
packet[1] = (byte) customSkin.model.id;
System.arraycopy(customSkin.texture, 0, packet, 2, customSkin.texture.length);
System.arraycopy(customSkin.texture, 0, packet, 2, 16384);
return packet;
}
public static PacketBuffer writeCreateCustomSkull(byte[] customSkin) {
int len = 3 + customSkin.length;
PacketBuffer ret = new PacketBuffer(Unpooled.buffer(len, len));
ret.writeByte(PACKET_INSTALL_NEW_SKIN);
ret.writeShort(customSkin.length);
ret.writeBytes(customSkin);
return ret;
}
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 byte[] writeMySkinCustomV4(CustomSkin customSkin) {
byte[] packet = new byte[2 + 12288];
packet[0] = (byte) PACKET_MY_SKIN_CUSTOM;
packet[1] = (byte) customSkin.model.id;
byte[] v3data = customSkin.texture;
for(int i = 0, j, k; i < 4096; ++i) {
j = i << 2;
k = i * 3 + 2;
packet[k] = v3data[j + 1];
packet[k + 1] = v3data[j + 2];
packet[k + 2] = (byte)((v3data[j + 3] >>> 1) | (v3data[j] & 0x80));
}
return packet;
}
public static EaglercraftUUID createEaglerURLSkinUUID(String skinUrl){

View File

@ -1,5 +1,6 @@
package net.lax1dude.eaglercraft.v1_8.profile;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
@ -98,7 +99,7 @@ public class SkinPreviewRenderer {
Minecraft.getMinecraft().getTextureManager().bindTexture(skinTexture);
}
model.render(null, 0.0f, 0.0f, (float)(System.currentTimeMillis() % 2000000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625f);
model.render(null, 0.0f, 0.0f, (float)(EagRuntime.steadyTimeMillis() % 2000000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625f);
if(capeTexture != null && model instanceof ModelPlayer) {
Minecraft.getMinecraft().getTextureManager().bindTexture(capeTexture);