This commit is contained in:
parent
5d08b027e6
commit
6cedb984fe
@ -1,4 +1,7 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
**1.0.1**
|
||||||
|
* Average Skin Color In Default Leather Armor
|
||||||
|
|
||||||
**1.0.0**
|
**1.0.0**
|
||||||
* Initial Release
|
* Initial Release
|
@ -10,7 +10,7 @@ org.gradle.jvmargs = -Xmx1G
|
|||||||
fabric_loader_version = 0.9.0+build.204
|
fabric_loader_version = 0.9.0+build.204
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 1.0.0
|
mod_version = 1.0.1
|
||||||
maven_group = com.thebrokenrail
|
maven_group = com.thebrokenrail
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
@ -4,6 +4,7 @@ import com.thebrokenrail.gestus.Gestus;
|
|||||||
import com.thebrokenrail.gestus.emote.EmoteLayer;
|
import com.thebrokenrail.gestus.emote.EmoteLayer;
|
||||||
import com.thebrokenrail.gestus.emote.EmotePart;
|
import com.thebrokenrail.gestus.emote.EmotePart;
|
||||||
import com.thebrokenrail.gestus.mixin.ArmorStandEntityAccessor;
|
import com.thebrokenrail.gestus.mixin.ArmorStandEntityAccessor;
|
||||||
|
import com.thebrokenrail.gestus.skin.SkinColor;
|
||||||
import com.thebrokenrail.gestus.util.ServerPlayerEntityExtension;
|
import com.thebrokenrail.gestus.util.ServerPlayerEntityExtension;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
@ -11,6 +12,8 @@ import net.minecraft.entity.damage.DamageSource;
|
|||||||
import net.minecraft.entity.data.TrackedData;
|
import net.minecraft.entity.data.TrackedData;
|
||||||
import net.minecraft.entity.decoration.ArmorStandEntity;
|
import net.minecraft.entity.decoration.ArmorStandEntity;
|
||||||
import net.minecraft.item.CrossbowItem;
|
import net.minecraft.item.CrossbowItem;
|
||||||
|
import net.minecraft.item.DyeableItem;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
@ -202,6 +205,25 @@ public class FakePlayerEntity extends ArmorStandEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SkinColor skinColor = null;
|
||||||
|
|
||||||
|
private void updateSkinColor() {
|
||||||
|
if (skinColor == null) {
|
||||||
|
skinColor = SkinColor.get(player.getUuid());
|
||||||
|
if (skinColor == null) {
|
||||||
|
skinColor = SkinColor.blank();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack colorItem(Item item, int color) {
|
||||||
|
ItemStack stack = new ItemStack(item);
|
||||||
|
if (color != -1) {
|
||||||
|
((DyeableItem) item).setColor(stack, color);
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
private ItemStack getFallbackItem(EquipmentSlot slot, ItemStack stack, boolean invisible) {
|
private ItemStack getFallbackItem(EquipmentSlot slot, ItemStack stack, boolean invisible) {
|
||||||
if (stack.isEmpty() && !invisible) {
|
if (stack.isEmpty() && !invisible) {
|
||||||
switch (slot) {
|
switch (slot) {
|
||||||
@ -210,13 +232,16 @@ public class FakePlayerEntity extends ArmorStandEntity {
|
|||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
case CHEST: {
|
case CHEST: {
|
||||||
return new ItemStack(Items.LEATHER_CHESTPLATE);
|
updateSkinColor();
|
||||||
|
return colorItem(Items.LEATHER_CHESTPLATE, skinColor.chest);
|
||||||
}
|
}
|
||||||
case LEGS: {
|
case LEGS: {
|
||||||
return new ItemStack(Items.LEATHER_LEGGINGS);
|
updateSkinColor();
|
||||||
|
return colorItem(Items.LEATHER_LEGGINGS, skinColor.legs);
|
||||||
}
|
}
|
||||||
case FEET: {
|
case FEET: {
|
||||||
return new ItemStack(Items.LEATHER_BOOTS);
|
updateSkinColor();
|
||||||
|
return colorItem(Items.LEATHER_BOOTS, skinColor.boots);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
|
116
src/main/java/com/thebrokenrail/gestus/skin/SkinColor.java
Normal file
116
src/main/java/com/thebrokenrail/gestus/skin/SkinColor.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package com.thebrokenrail.gestus.skin;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class SkinColor {
|
||||||
|
public final int chest;
|
||||||
|
public final int legs;
|
||||||
|
public final int boots;
|
||||||
|
|
||||||
|
private SkinColor(int chest, int legs, int boots) {
|
||||||
|
this.chest = chest;
|
||||||
|
this.legs = legs;
|
||||||
|
this.boots = boots;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Color {
|
||||||
|
private final int data;
|
||||||
|
|
||||||
|
private Color(int data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color(int red, int green, int blue) {
|
||||||
|
data = 255 << 24 | (red & 255) << 16 | (green & 255) << 8 | (blue & 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color(long red, long green, long blue) {
|
||||||
|
this((int) red, (int) green, (int) blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRed() {
|
||||||
|
return data >> 16 & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGreen() {
|
||||||
|
return data >> 8 & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlue() {
|
||||||
|
return data & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getData() {
|
||||||
|
return (getRed() << 16) | (getGreen() << 8) | getBlue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color averageColor(BufferedImage image, int x0, int y0, int w, int h) {
|
||||||
|
int x1 = x0 + w;
|
||||||
|
int y1 = y0 + h;
|
||||||
|
|
||||||
|
long sumRed = 0;
|
||||||
|
long sumGreen = 0;
|
||||||
|
long sumBlue = 0;
|
||||||
|
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
for (int x = x0; x < x1; x++) {
|
||||||
|
for (int y = y0; y < y1; y++) {
|
||||||
|
int data = image.getRGB(x, y);
|
||||||
|
if ((data >> 24 & 255) == 255) {
|
||||||
|
Color pixel = new Color(data);
|
||||||
|
sumRed += pixel.getRed();
|
||||||
|
sumGreen += pixel.getGreen();
|
||||||
|
sumBlue += pixel.getBlue();
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Color(sumRed / num, sumGreen / num, sumBlue / num);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color averageColor(Color color1, Color color2) {
|
||||||
|
int sumRed = color1.getRed() + color2.getRed();
|
||||||
|
long sumGreen = color1.getGreen() + color2.getGreen();
|
||||||
|
long sumBlue = color1.getBlue() + color2.getBlue();
|
||||||
|
return new Color(sumRed / 2, sumGreen / 2, sumBlue / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SkinColor get(UUID uuid) {
|
||||||
|
String skin = SkinJSON.get(uuid);
|
||||||
|
if (skin != null) {
|
||||||
|
URL url;
|
||||||
|
try {
|
||||||
|
url = new URL(skin);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedImage image;
|
||||||
|
try {
|
||||||
|
image = ImageIO.read(url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int chest = averageColor(image, 16, 20, 23, 11).getData();
|
||||||
|
int legs = averageColor(averageColor(image, 16, 52, 11, 11), averageColor(image, 0, 20, 11, 11)).getData();
|
||||||
|
int boots = averageColor(averageColor(image, 20, 48, 7, 3), averageColor(image, 44, 16, 7, 3)).getData();
|
||||||
|
|
||||||
|
return new SkinColor(chest, legs, boots);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SkinColor blank() {
|
||||||
|
return new SkinColor(-1, -1, -1);
|
||||||
|
}
|
||||||
|
}
|
79
src/main/java/com/thebrokenrail/gestus/skin/SkinJSON.java
Normal file
79
src/main/java/com/thebrokenrail/gestus/skin/SkinJSON.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package com.thebrokenrail.gestus.skin;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
final class SkinJSON {
|
||||||
|
private static class Response {
|
||||||
|
public Property[] properties = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Property {
|
||||||
|
public String name = null;
|
||||||
|
public String value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Data {
|
||||||
|
public Map<String, Texture> textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Texture {
|
||||||
|
public String url = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String urlToString(String urlStr) {
|
||||||
|
try {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
URL url = new URL(urlStr);
|
||||||
|
|
||||||
|
try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
stringBuilder.append(line);
|
||||||
|
stringBuilder.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String SKIN_TEXTURE_KEY = "SKIN";
|
||||||
|
|
||||||
|
static String get(UUID uuid) {
|
||||||
|
String url = String.format("https://sessionserver.mojang.com/session/minecraft/profile/%s", uuid.toString().replace("-", ""));
|
||||||
|
String data = urlToString(url);
|
||||||
|
|
||||||
|
if (data != null) {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
Response response = gson.fromJson(data, Response.class);
|
||||||
|
|
||||||
|
if (response != null && response.properties != null) {
|
||||||
|
for (Property property : response.properties) {
|
||||||
|
if ("textures".equals(property.name)) {
|
||||||
|
String texturesJSON = new String(Base64.getDecoder().decode(property.value));
|
||||||
|
Data textures = gson.fromJson(texturesJSON, Data.class);
|
||||||
|
|
||||||
|
if (textures.textures.containsKey(SKIN_TEXTURE_KEY)) {
|
||||||
|
Texture skin = textures.textures.get(SKIN_TEXTURE_KEY);
|
||||||
|
return skin.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user