Move everything related to PonyData parsing into the PonyData class

This commit is contained in:
Sollace 2019-07-16 14:20:18 +02:00
parent a7664bbe71
commit 0dab332a0e
3 changed files with 98 additions and 118 deletions

View file

@ -1,7 +1,6 @@
package com.minelittlepony.client.pony;
import com.google.common.base.MoreObjects;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.PonyRenderManager;
import com.minelittlepony.client.render.IPonyRender;
import com.minelittlepony.client.transform.PonyTransformation;
@ -11,8 +10,6 @@ import com.minelittlepony.pony.meta.Race;
import com.minelittlepony.pony.meta.Size;
import net.minecraft.block.Material;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
@ -20,31 +17,17 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.resource.Resource;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import static com.mojang.blaze3d.platform.GlStateManager.getTexLevelParameter;
import static org.lwjgl.opengl.GL11.*;
@Immutable
public class Pony implements IPony {
private static final AtomicInteger ponyCount = new AtomicInteger();
private static final NativeImage.Format[] formats = NativeImage.Format.values();
private final int ponyId = ponyCount.getAndIncrement();
private final Identifier texture;
private final IPonyData metadata;
@ -56,19 +39,7 @@ public class Pony implements IPony {
}
Pony(Identifier resource) {
texture = resource;
metadata = checkSkin(texture);
}
private IPonyData checkSkin(Identifier resource) {
IPonyData data = checkPonyMeta(resource);
if (data != null) {
return data;
}
try (NativeImage ponyTexture = getBufferedImage(resource)) {
return checkSkin(ponyTexture);
}
this(resource, PonyData.parse(resource));
}
@Override
@ -79,81 +50,6 @@ public class Pony implements IPony {
}
}
@Nullable
private IPonyData checkPonyMeta(Identifier resource) {
try {
Resource res = MinecraftClient.getInstance().getResourceManager().getResource(resource);
PonyData data = res.getMetadata(PonyData.SERIALISER);
if (data != null) {
return data;
}
} catch (FileNotFoundException e) {
// Ignore uploaded texture
} catch (IOException e) {
MineLittlePony.logger.warn("Unable to read {} metadata", resource, e);
}
return null;
}
private static NativeImage.Format getFormat(int glFormat) {
for (NativeImage.Format i : formats) {
if (i.getPixelDataFormat() == glFormat) {
return i;
}
}
throw new RuntimeException("Unsupported image format");
}
@Nullable
private static NativeImage getBufferedImage(@Nullable Identifier resource) {
if (resource == null) {
return null;
}
MinecraftClient mc = MinecraftClient.getInstance();
TextureManager textures = mc.getTextureManager();
if (!mc.isOnThread()) {
throw new RuntimeException("This can only be called from the main thread.");
}
// recreate NativeImage from the GL matrix
textures.bindTexture(resource);
int format = getTexLevelParameter(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT);
int width = getTexLevelParameter(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH);
int height = getTexLevelParameter(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT);
if (width * height == 0) {
throw new IllegalStateException("GL texture not uploaded yet");
}
NativeImage.Format channels = getFormat(format);
NativeImage image = new NativeImage(channels, width, height, false);
// This allocates a new array to store the image every time.
// Don't do this every time. Keep a cache and store it so we don't destroy memory.
try {
image.loadFromTextureImage(0, false);
} catch (IllegalStateException e) {
image.close();
throw e;
}
return image;
}
private IPonyData checkSkin(@Nullable NativeImage bufferedimage) {
if (bufferedimage == null) {
return new PonyData();
}
MineLittlePony.logger.debug("\tStart skin check for pony #{} with image {}.", ponyId, bufferedimage);
return PonyData.parse(bufferedimage);
}
@Override
public boolean isPerformingRainboom(LivingEntity entity) {
Vec3d motion = entity.getVelocity();

View file

@ -1,9 +1,14 @@
package com.minelittlepony.client.pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.resource.Resource;
import net.minecraft.util.Identifier;
import com.google.common.base.MoreObjects;
import com.google.gson.annotations.Expose;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.util.render.NativeUtil;
import com.minelittlepony.pony.IPonyData;
import com.minelittlepony.pony.meta.Gender;
import com.minelittlepony.pony.meta.Race;
@ -14,8 +19,11 @@ import com.minelittlepony.pony.meta.Wearable;
import com.minelittlepony.util.animation.BasicEasingInterpolator;
import com.minelittlepony.util.animation.IInterpolator;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
@ -25,7 +33,33 @@ import javax.annotation.concurrent.Immutable;
@Immutable
public class PonyData implements IPonyData {
public static final PonyDataSerialiser SERIALISER = new PonyDataSerialiser();
private static final PonyDataSerialiser SERIALISER = new PonyDataSerialiser();
/**
* Parses the given resource into a new IPonyData.
* This may either come from an attached json file or the image itself.
*/
public static IPonyData parse(@Nullable Identifier identifier) {
if (identifier == null) {
return new PonyData();
}
try {
Resource res = MinecraftClient.getInstance().getResourceManager().getResource(identifier);
PonyData data = res.getMetadata(SERIALISER);
if (data != null) {
return data;
}
} catch (FileNotFoundException e) {
// Ignore uploaded texture
} catch (IOException e) {
MineLittlePony.logger.warn("Unable to read {} metadata", identifier, e);
}
return NativeUtil.parseImage(identifier, PonyData::new);
}
@Expose
private final Race race;
@ -100,6 +134,11 @@ public class PonyData implements IPonyData {
return wearables[wearable.ordinal()];
}
@Override
public IInterpolator getInterpolator(UUID interpolatorId) {
return BasicEasingInterpolator.getInstance(interpolatorId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
@ -111,16 +150,4 @@ public class PonyData implements IPonyData {
.add("glowColor", "#" + Integer.toHexString(glowColor))
.toString();
}
@Override
public IInterpolator getInterpolator(UUID interpolatorId) {
return BasicEasingInterpolator.getInstance(interpolatorId);
}
/**
* Parses an image buffer into a new IPonyData representing the values stored in it's individual trigger pixels.
*/
public static IPonyData parse(NativeImage image) {
return new PonyData(image);
}
}

View file

@ -0,0 +1,57 @@
package com.minelittlepony.client.util.render;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.util.Identifier;
import java.util.function.Function;
import static com.mojang.blaze3d.platform.GlStateManager.getTexLevelParameter;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_HEIGHT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_INTERNAL_FORMAT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WIDTH;
public class NativeUtil {
private static final NativeImage.Format[] formats = NativeImage.Format.values();
public static NativeImage.Format getFormat(int glFormat) {
for (NativeImage.Format i : formats) {
if (i.getPixelDataFormat() == glFormat) {
return i;
}
}
throw new RuntimeException("Unsupported image format");
}
public static <T> T parseImage(Identifier resource, Function<NativeImage, T> consumer) {
MinecraftClient mc = MinecraftClient.getInstance();
TextureManager textures = mc.getTextureManager();
if (!mc.isOnThread()) {
throw new IllegalStateException("This can only be called from the main thread.");
}
// recreate NativeImage from the GL matrix
textures.bindTexture(resource);
int format = getTexLevelParameter(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT);
int width = getTexLevelParameter(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH);
int height = getTexLevelParameter(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT);
if (width * height == 0) {
throw new IllegalStateException("GL texture not uploaded yet");
}
try (NativeImage image = new NativeImage(getFormat(format), width, height, false)) {
// This allocates a new array to store the image every time.
// Don't do this every time. Keep a cache and store it so we don't destroy memory.
image.loadFromTextureImage(0, false);
return consumer.apply(image);
}
}
}