Fix issues with the skin menu.

Add a button to the main menu for skins
Add overriding skins with a resource pack. See the skins.json
Some default ponies are added. Spawn them using Citizens.
Etc.
This commit is contained in:
Matthew Messinger 2016-08-25 01:36:00 -04:00
parent 79ab9d51ee
commit c219c66aef
68 changed files with 598 additions and 45 deletions

View file

@ -26,7 +26,7 @@ apply plugin: 'org.spongepowered.mixin'
apply plugin: 'mnm.gradle.ap-ide'
group = 'com.brohoof.minelp'
version = '1.10.2.2'
version = '1.10.2.3'
description = 'Mine Little Pony'
minecraft {
@ -35,6 +35,7 @@ minecraft {
runDir = 'run'
replace '@VERSION@',project.version
}
sourceSets {
def deps = [
configurations.forgeGradleMcDeps,
@ -49,40 +50,57 @@ sourceSets {
refMap = 'mixin.minelp.refmap.json'
compileClasspath += hdskins.output
}
forge {
compileClasspath += files(deps + [ main.output, api.output ])
}
}
dependencies.testCompile 'junit:junit:4.12'
litemod.json {
author = "Verdana, Rene_Z, Mumfrey, JoyJoy"
description = "Mine Little Pony turns players and mobs into ponies"
description.litemodminelittlepony = """Mine Little Pony turns players and mobs into ponies
Press F9 ingame to access settings"""
description.litemodhdskinsmod = """Seperate skin server for Mine Little Pony that also supports HD skins.
Access via Skin Manager key binding (default: F1) in the main menu."""
mixinConfigs += ['mixin.minelp.json', 'mixin.hdskins.json']
author = 'Verdana, Rene_Z, Mumfrey, JoyJoy'
description = 'Mine Little Pony turns players and mobs into ponies'
description.minelittlepony = '''\
Mine Little Pony turns players and mobs into ponies
Press F9 ingame to access settings'''.stripIndent()
description.hdskinsmod = '''\
Seperate skin server for Mine Little Pony that also supports HD skins.
Access via Skin Manager key binding (default: F1) in the main menu.'''.stripIndent()
mixinConfigs += [
'mixin.minelp.json',
'mixin.hdskins.json'
]
}
afterEvaluate {
dependencies {
// add mixin to the factory path
// use same version as liteloader
def liteloader = project.plugins['net.minecraftforge.gradle.liteloader']
def artifact = liteloader.artifact.libraries.collect{it.name}.find{it.contains 'mixin'}
def artifact = liteloader.artifact.libraries
.collect {it.name}
.find {it.contains 'mixin'}
factory artifact
}
processor {
// tell the processor where the reobf file is
options.reobfSrgFile = mixin.reobfSrgFile
}
}
jar {
from sourceSets.findAll { it.name != 'api' }*.output
from sourceSets.hdskins.output
from litemod.outputs
}
sourceJar {
// add hdskins sources
from sourceSets.hdskins.allSource
}
task srgJar(type: Jar) {
from sourceSets.findAll { it.name != 'api' }*.output
from sourceSets.hdskins.output
from litemod.outputs
classifier "mc${minecraft.version}-srg"
classifier "mc$minecraft.version-srg"
baseName "mod-${project.name.toLowerCase()}"
extension 'litemod'
}
reobf {
srgJar {
mappingType = 'SEARGE'
@ -91,6 +109,8 @@ reobf {
mixin {
defaultObfuscationEnv notch
}
// windows only
task deploy(type: Copy, dependsOn: build) {
from jar.archivePath
into file("$System.env.APPDATA/.minecraft/mods")

View file

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit!
#Mon Aug 22 11:16:46 EDT 2016
build.number=246
#Wed Aug 24 19:20:55 EDT 2016
build.number=250

View file

@ -0,0 +1,26 @@
package com.voxelmodpack.hdskins;
import java.awt.image.BufferedImage;
import net.minecraft.client.renderer.texture.DynamicTexture;
public class DynamicTextureImage extends DynamicTexture {
private BufferedImage image;
public DynamicTextureImage(BufferedImage bufferedImage) {
super(bufferedImage);
this.image = bufferedImage;
}
public BufferedImage getImage() {
return image;
}
@Override
public void deleteGlTexture() {
super.deleteGlTexture();
this.image = null;
}
}

View file

@ -31,6 +31,7 @@ import com.mojang.authlib.properties.Property;
import com.mojang.util.UUIDTypeAdapter;
import com.mumfrey.liteloader.core.LiteLoader;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
import com.voxelmodpack.hdskins.resource.SkinResourceManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IImageBuffer;
@ -38,10 +39,12 @@ import net.minecraft.client.renderer.ThreadDownloadImageData;
import net.minecraft.client.renderer.texture.ITextureObject;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.client.resources.SkinManager.SkinAvailableCallback;
import net.minecraft.util.ResourceLocation;
public final class HDSkinManager {
public final class HDSkinManager implements IResourceManagerReloadListener {
public static final HDSkinManager INSTANCE = new HDSkinManager();
private static final ResourceLocation LOADING = new ResourceLocation("LOADING");
@ -55,11 +58,18 @@ public final class HDSkinManager {
private Map<UUID, Map<Type, ResourceLocation>> skinCache = Maps.newHashMap();
private List<ISkinModifier> skinModifiers = Lists.newArrayList();
private HDSkinManager() {}
private SkinResourceManager resources = new SkinResourceManager();
public HDSkinManager() {}
public Optional<ResourceLocation> getSkinLocation(GameProfile profile1, Type type, boolean loadIfAbsent) {
if (!enabled)
return Optional.absent();
ResourceLocation skin = this.resources.getPlayerTexture(profile1, type);
if (skin != null)
return Optional.of(skin);
// try to recreate a broken gameprofile
// happens when server sends a random profile with skin and displayname
Property prop = Iterables.getFirst(profile1.getProperties().get("textures"), null);
@ -85,7 +95,7 @@ public final class HDSkinManager {
this.skinCache.put(profile.getId(), Maps.<Type, ResourceLocation> newHashMap());
}
ResourceLocation skin = this.skinCache.get(profile.getId()).get(type);
skin = this.skinCache.get(profile.getId()).get(type);
if (skin == null) {
if (loadIfAbsent) {
skinCache.get(profile.getId()).put(type, LOADING);
@ -252,4 +262,9 @@ public final class HDSkinManager {
skin.convertSkin(image, dest);
}
}
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
this.resources.onResourceManagerReload(resourceManager);
}
}

View file

@ -8,6 +8,7 @@ import javax.imageio.ImageIO;
import com.google.common.collect.Iterables;
import com.mojang.authlib.GameProfile;
import com.voxelmodpack.hdskins.DynamicTextureImage;
import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.IMetaHandler;
import com.voxelmodpack.hdskins.ImageBufferDownloadHD;
@ -73,7 +74,7 @@ public class EntityPlayerModel extends EntityLivingBase {
return;
}
this.localSkinTexture = new DynamicTexture(bufferedImage);
this.localSkinTexture = new DynamicTextureImage(bufferedImage);
this.localSkinResource = this.textureManager.getDynamicTextureLocation("localSkinPreview", this.localSkinTexture);
this.hasLocalTexture = true;
}

View file

@ -0,0 +1,22 @@
package com.voxelmodpack.hdskins.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
public class GuiButtonSkins extends GuiButton {
public GuiButtonSkins(int buttonId, int x, int y) {
super(buttonId, x, y, 20, 20, "");
}
@Override
public void drawButton(Minecraft mc, int mouseX, int mouseY) {
super.drawButton(mc, mouseX, mouseY);
ItemStack stack = new ItemStack(Items.LEATHER_LEGGINGS, 1, 0);
Items.LEATHER_LEGGINGS.setColor(stack, 0x3c5dcb);
mc.getRenderItem().renderItemIntoGUI(stack, this.xPosition + 2, this.yPosition + 2);
}
}

View file

@ -239,7 +239,7 @@ public class GuiMetaHandler extends GuiScreen implements IMetaHandler {
if (prefs.has(HDSkinManager.METADATA_KEY)) {
String meta = prefs.get(HDSkinManager.METADATA_KEY);
Map<String, String> data = Maps.newHashMap();
for (String key : Splitter.on(',').split(meta)) {
for (String key : Splitter.on(',').omitEmptyStrings().trimResults().split(meta)) {
if (prefs.has(key)) {
data.put(key, prefs.get(key));
}

View file

@ -43,16 +43,19 @@ public class RenderPlayerModel<M extends EntityPlayerModel> extends RenderLiving
return false;
}
public ModelPlayer getEntityModel(M entity) {
if (entity.metaHandler != null && entity.metaHandler.get("slim").isPresent()) {
boolean skinny = "true".equals(entity.metaHandler.get("slim").get());
return skinny ? THIN : FAT;
}
return FAT;
}
@Override
public void doRender(M par1Entity, double par2, double par4, double par6, float par8, float par9) {
if (par1Entity.metaHandler != null && par1Entity.metaHandler.get("slim").isPresent()) {
boolean skinny = "true".equals(par1Entity.metaHandler.get("slim").get());
this.mainModel = skinny ? THIN : FAT;
} else {
this.mainModel = FAT;
}
ModelPlayer player = (ModelPlayer) this.getMainModel();
ModelPlayer player = this.getEntityModel(par1Entity);
this.mainModel = player;
Set<EnumPlayerModelParts> parts = Minecraft.getMinecraft().gameSettings.getModelParts();
player.bipedHeadwear.isHidden = !parts.contains(EnumPlayerModelParts.HAT);

View file

@ -0,0 +1,32 @@
package com.voxelmodpack.hdskins.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.voxelmodpack.hdskins.gui.GuiButtonSkins;
import com.voxelmodpack.hdskins.gui.GuiSkins;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiScreen;
@Mixin(GuiMainMenu.class)
public class MixinGuiMainMenu extends GuiScreen {
private static final int SKINS = 5000;
@Inject(method = "initGui()V", at = @At("RETURN"))
private void onInit(CallbackInfo ci) {
this.buttonList.add(new GuiButtonSkins(SKINS, width - 50, height - 50));
}
@Inject(method = "actionPerformed(Lnet/minecraft/client/gui/GuiButton;)V", at = @At("RETURN"))
private void onActionPerformed(GuiButton button, CallbackInfo ci) {
if (button.id == SKINS) {
this.mc.displayGuiScreen(new GuiSkins());
}
}
}

View file

@ -14,6 +14,7 @@ import com.voxelmodpack.hdskins.gui.RenderPlayerModel;
import com.voxelmodpack.voxelmenu.IPanoramaRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IReloadableResourceManager;
public class LiteModHDSkinsMod implements HDSkinsMod {
@Override
@ -38,6 +39,8 @@ public class LiteModHDSkinsMod implements HDSkinsMod {
var5.printStackTrace();
}
IReloadableResourceManager irrm = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager();
irrm.registerReloadListener(HDSkinManager.INSTANCE);
}
@Override

View file

@ -0,0 +1,22 @@
package com.voxelmodpack.hdskins.resource;
import java.util.List;
import java.util.UUID;
import net.minecraft.util.ResourceLocation;
class SkinData {
List<Skin> skins;
}
class Skin {
String name;
UUID uuid;
private String skin;
public ResourceLocation getTexture() {
return new ResourceLocation("hdskins", String.format("textures/skins/%s.png", skin));
}
}

View file

@ -0,0 +1,103 @@
package com.voxelmodpack.hdskins.resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.util.ResourceLocation;
public class SkinResourceManager implements IResourceManagerReloadListener {
private Map<UUID, Skin> uuidSkins = Maps.newHashMap();
private Map<String, Skin> namedSkins = Maps.newHashMap();
private Map<ResourceLocation, SkinThread> converted = Maps.newHashMap();
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
try {
uuidSkins.clear();
namedSkins.clear();
for (SkinThread loc : converted.values()) {
loc.deleteTexture();
}
converted.clear();
for (IResource res : resourceManager.getAllResources(new ResourceLocation("hdskins", "textures/skins/skins.json"))) {
try {
SkinData data = getSkinData(res.getInputStream());
for (Skin s : data.skins) {
if (s.uuid != null) {
uuidSkins.put(s.uuid, s);
}
if (s.name != null) {
namedSkins.put(s.name, s);
}
}
} catch (JsonParseException je) {
LiteLoaderLogger.warning(je, "Invalid skins.json in %s", res.getResourcePackName());
}
}
} catch (IOException e) {
// ignore
}
}
private SkinData getSkinData(InputStream stream) {
try {
return new Gson().fromJson(new InputStreamReader(stream), SkinData.class);
} finally {
IOUtils.closeQuietly(stream);
}
}
@Nullable
public ResourceLocation getPlayerTexture(GameProfile profile, Type type) {
if (type != Type.SKIN)
// not supported
return null;
Skin skin = getSkin(profile);
if (skin != null) {
ResourceLocation res = skin.getTexture();
if (res != null) {
SkinThread conv = this.converted.get(res);
if (conv == null) {
// read and convert in a new thread
this.converted.put(res, conv = new SkinThread(res));
}
// gotta stay in this thread to load it
if (conv.isReady()) {
conv.uploadSkin();
}
return conv.getResource();
}
}
return null;
}
@Nullable
private Skin getSkin(GameProfile profile) {
Skin skin = this.uuidSkins.get(profile.getId());
if (skin == null) {
skin = this.namedSkins.get(profile.getName());
}
return skin;
}
}

View file

@ -0,0 +1,69 @@
package com.voxelmodpack.hdskins.resource;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
import com.voxelmodpack.hdskins.DynamicTextureImage;
import com.voxelmodpack.hdskins.ImageBufferDownloadHD;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.util.ResourceLocation;
public class SkinThread implements Runnable {
private ResourceLocation original;
private ResourceLocation updated;
private BufferedImage image;
public SkinThread(ResourceLocation loc) {
this.original = loc;
new Thread(this).start();
}
@Override
public void run() {
image = new ImageBufferDownloadHD().parseUserSkin(getImage(original));
}
@Nullable
private static BufferedImage getImage(ResourceLocation res) {
try {
InputStream in = Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream();
try {
return TextureUtil.readBufferedImage(in);
} finally {
IOUtils.closeQuietly(in);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public ResourceLocation getResource() {
return this.updated;
}
public void deleteTexture() {
Minecraft.getMinecraft().getTextureManager().deleteTexture(updated);
}
public boolean isReady() {
return image != null;
}
public void uploadSkin() {
ResourceLocation conv = new ResourceLocation("hdskins-converted", original.getResourcePath());
Minecraft.getMinecraft().getTextureManager().loadTexture(conv, new DynamicTextureImage(image));
updated = conv;
image = null;
}
}

View file

@ -4,6 +4,7 @@
"package": "com.voxelmodpack.hdskins.mixin",
"refmap": "mixin.hdskins.refmap.json",
"mixins": [
"MixinGuiMainMenu",
"MixinImageBufferDownload",
"MixinPlayerInfo",
"MixinSkullRenderer"

View file

@ -17,7 +17,6 @@ import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.gui.GuiSkins;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.settings.KeyBinding;
@ -40,7 +39,6 @@ public class MineLittlePony {
private static final String SKIN_SERVER_URL = "minelpskins.voxelmodpack.com";
private static final String GATEWAY_URL = "minelpskinmanager.voxelmodpack.com";
private static final KeyBinding SETTINGS_GUI = new KeyBinding("Settings", Keyboard.KEY_F9, "Mine Little Pony");
private static final KeyBinding SKIN_MANAGER = new KeyBinding("Skin Manager", Keyboard.KEY_F1, "Mine Little Pony");
private static MineLittlePony instance;
@ -54,7 +52,6 @@ public class MineLittlePony {
void init() {
LiteLoader.getInput().registerKeyBinding(SETTINGS_GUI);
LiteLoader.getInput().registerKeyBinding(SKIN_MANAGER);
this.config = new PonyConfig();
this.ponyManager = new PonyManager(config);
@ -104,11 +101,9 @@ public class MineLittlePony {
minecraft.displayGuiScreen(new PonySettingPanel());
}
boolean pressed = minecraft.currentScreen instanceof GuiMainMenu
&& Keyboard.isKeyDown(SKIN_MANAGER.getKeyCode());
boolean skins = minecraft.currentScreen instanceof GuiSkins
&& !(minecraft.currentScreen instanceof GuiSkinsMineLP);
if (pressed || skins) {
if (skins) {
minecraft.displayGuiScreen(new GuiSkinsMineLP(ponyManager));
}
HDSkinManager.INSTANCE.setEnabled(config.hd);

View file

@ -4,8 +4,6 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import com.brohoof.minelittlepony.model.PMAPI;
import com.brohoof.minelittlepony.model.PlayerModel;
import com.brohoof.minelittlepony.util.MineLPLogger;
@ -17,12 +15,15 @@ import com.google.common.collect.Lists;
import com.mojang.authlib.GameProfile;
import com.mumfrey.webprefs.WebPreferencesManager;
import com.mumfrey.webprefs.interfaces.IWebPreferences;
import com.voxelmodpack.hdskins.DynamicTextureImage;
import com.voxelmodpack.hdskins.HDSkinManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.renderer.ThreadDownloadImageData;
import net.minecraft.client.renderer.texture.ITextureObject;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.IResource;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
@ -57,6 +58,7 @@ public class Pony {
public void invalidateSkinCheck() {
this.skinChecked = false;
metadata = new PonyData();
}
public void checkSkin() {
@ -119,7 +121,8 @@ public class Pony {
public BufferedImage getBufferedImage(ResourceLocation textureResourceLocation) {
BufferedImage skinImage = null;
try {
skinImage = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(textureResourceLocation).getInputStream());
IResource skin = Minecraft.getMinecraft().getResourceManager().getResource(textureResourceLocation);
skinImage = TextureUtil.readBufferedImage(skin.getInputStream());
MineLPLogger.debug("Obtained skin from resource location %s", textureResourceLocation);
// this.checkSkin(skinImage);
} catch (IOException var6) {
@ -134,6 +137,8 @@ public class Pony {
MineLPLogger.debug(e, "Successfully reflected downloadedImage from texture object");
// this.checkSkin(skinImage);
}
} else if (e2 instanceof DynamicTextureImage) {
skinImage = ((DynamicTextureImage) e2).getImage();
}
} catch (Exception var5) {

View file

@ -26,7 +26,7 @@ public class PonyData {
.put(0x534b76, PonySize.TALL)
.build();
private PonyRace race = PonyRace.EARTH;
private PonyRace race;
private TailLengths tailSize = TailLengths.FULL;
private PonyGender gender = PonyGender.MARE;
private PonySize size = PonySize.NORMAL;

View file

@ -10,6 +10,7 @@ import com.brohoof.minelittlepony.model.PlayerModel;
import com.google.common.base.Optional;
import com.voxelmodpack.hdskins.gui.RenderPlayerModel;
import net.minecraft.client.model.ModelPlayer;
import net.minecraft.client.renderer.entity.RenderManager;
public class RenderPonyModel extends RenderPlayerModel<EntityPonyModel> {
@ -19,8 +20,7 @@ public class RenderPonyModel extends RenderPlayerModel<EntityPonyModel> {
}
@Override
protected void renderModel(EntityPonyModel playermodel, float par2, float par3, float par4, float par5, float par6, float par7) {
this.bindEntityTexture(playermodel);
public ModelPlayer getEntityModel(EntityPonyModel playermodel) {
Pony thePony = MineLittlePony.getInstance().getManager().getPonyFromResourceRegistry(this.getEntityTexture(playermodel));
thePony.invalidateSkinCheck();
thePony.checkSkin();
@ -46,9 +46,9 @@ public class RenderPonyModel extends RenderPlayerModel<EntityPonyModel> {
// TODO small arms
PlayerModel pm = thePony.getModel(true, false);
this.mainModel = pm.getModel();
pm.apply(thePony.metadata);
this.mainModel.render(playermodel, par2, par3, par4, par5, par6, par7);
return pm.getModel();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,022 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

View file

@ -0,0 +1,236 @@
{
"skins": [
{
"skin": "applebloom",
"name": "Apple Bloom!"
},
{
"skin": "applejack",
"name": "Applejack!"
},
{
"skin": "babsseed",
"name": "Babs Seed!"
},
{
"skin": "berrypunch",
"name": "Berry Punch!"
},
{
"skin": "bigmac",
"name": "Big Mac!"
},
{
"skin": "bigmac",
"name": "Big Macintosh!"
},
{
"skin": "blockwork",
"name": "Blockwork!"
},
{
"skin": "bonbon",
"name": "Bon Bon!"
},
{
"skin": "braeburn",
"name": "Braeburn!"
},
{
"skin": "cadence",
"name": "Cadance!"
},
{
"skin": "cadence",
"name": "Cadence!"
},
{
"skin": "caramel",
"name": "Caramel!"
},
{
"skin": "carrottop",
"name": "Carrot Top!"
},
{
"skin": "celestia",
"name": "Celestia!"
},
{
"skin": "changeling",
"name": "Changeling!"
},
{
"skin": "changeling",
"name": "Changling!"
},
{
"skin": "cheerilee",
"name": "Cheerilee!"
},
{
"skin": "chrysalis",
"name": "Chrysalis!"
},
{
"skin": "colgate",
"name": "Colgate!"
},
{
"skin": "cranky",
"name": "Cranky!"
},
{
"skin": "daringdo",
"name": "Daring Do!"
},
{
"skin": "derpyhooves",
"name": "Derpy Hooves!"
},
{
"skin": "derpy",
"name": "Derpy!"
},
{
"skin": "derpy",
"name": "DerpyHooves!"
},
{
"skin": "diamondtiara",
"name": "Diamond Tiara!"
},
{
"skin": "fleetfoot",
"name": "Fleetfoot!"
},
{
"skin": "fluttershy",
"name": "Fluttershy!"
},
{
"skin": "grannysmith",
"name": "Granny Smith!"
},
{
"skin": "lemonhearts",
"name": "Lemon Hearts!"
},
{
"skin": "lemonhearts",
"name": "LemonHearts!"
},
{
"skin": "luna",
"name": "Luna!"
},
{
"skin": "lyra",
"name": "Lyra!"
},
{
"skin": "mayormare",
"name": "Mayor Mare!"
},
{
"skin": "mrcake",
"name": "Mr Cake!"
},
{
"skin": "mrscake",
"name": "Mrs Cake!"
},
{
"skin": "octavia",
"name": "Octavia!"
},
{
"skin": "pinkiepie",
"name": "Pinkie Pie!"
},
{
"skin": "pinkiepie",
"name": "PinkiePie!"
},
{
"skin": "rainbowdash",
"name": "Rainbow Dash!"
},
{
"skin": "rainbowdash",
"name": "RainbowDash!"
},
{
"skin": "rarity",
"name": "Rarity!"
},
{
"skin": "royalguard",
"name": "Royal Guard!"
},
{
"skin": "royalguard",
"name": "RoyalGuard!"
},
{
"skin": "scootaloo",
"name": "Scootaloo!"
},
{
"skin": "shiningarmor",
"name": "Shining Armor!"
},
{
"skin": "shiningarmor",
"name": "Shining Armour!"
},
{
"skin": "silverspoon",
"name": "Silver Spoon!"
},
{
"skin": "soarin",
"name": "Soarin!"
},
{
"skin": "soarinoriginal",
"name": "SoarinOriginal!"
},
{
"skin": "spitfire",
"name": "Spitfire!"
},
{
"skin": "sweetiebelle",
"name": "Sweetie Belle!"
},
{
"skin": "trixie",
"name": "Trixie!"
},
{
"skin": "twilight",
"name": "Twilight!"
},
{
"skin": "twilight",
"name": "TwilightSparkle!"
},
{
"skin": "twilightsparkleoriginal",
"name": "TwilightSparkleOriginal!"
},
{
"skin": "twist",
"name": "Twist!"
},
{
"skin": "vinylscratch",
"name": "Vinyl Scratch!"
},
{
"skin": "wonderbolt",
"name": "Wonderbolt!"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB