// Path: src/main/java/com/github/worldsender/mcanm/common/resource/IResourceLocation.java
// public interface IResourceLocation {
// 	/**
// 	 * For data that has no definite location, this is suitable (e.g. one-time streams)
// 	 */
// 	public static final IResourceLocation UNKNOWN_LOCATION = new IResourceLocation() {
// 		@Override
// 		public IResource open() throws IOException {
// 			throw new NoSuchFileException("Unknown location");
// 		}
// 
// 		@Override
// 		public String getResourceName() {
// 			return "<unknown resource>";
// 		}
// 
// 		@Override
// 		public boolean shouldCache() {
// 			return false;
// 		}
// 
// 		@Override
// 		public void registerReloadListener(Consumer<IResourceLocation> reloadListener) {
// 			reloadListener.accept(this);
// 			// Don't store it, this location won't change
// 		}
// 	};
// 
// 	/**
// 	 * Opens the resource location described by this resource location.
// 	 * 
// 	 * @return an empty optional if the resource is currently (expectedly) absent
// 	 * @throws IOException
// 	 *             if the resource is absent unexpectedly
// 	 */
// 	IResource open() throws IOException;
// 
// 	/**
// 	 * Registers a listener that is being fired every time this resource changes. What "changes" means is deliberately
// 	 * left unspecified but a good example would be whenever the {@link Minecraft#getResourceManager()} changes, for
// 	 * example when a new resource pack is loaded.<br>
// 	 * <b>The initial stick is considered a change already, so this method should also fire the listener once.</b>
// 	 * 
// 	 * @param reloadListener
// 	 */
// 	void registerReloadListener(Consumer<IResourceLocation> reloadListener);
// 
// 	/**
// 	 * A descriptive name of the resource, perhaps the path
// 	 * 
// 	 * @return
// 	 */
// 	String getResourceName();
// 
// 	/**
// 	 * Returns false if this resource should not be cached, e.g. it is a one-time stream. When a
// 	 * {@link IResourceLocation} may get cached, {@link #open()} should succeed multiple times and return the same data
// 	 * every time, until the resource is reloaded.
// 	 * 
// 	 * @return
// 	 */
// 	boolean shouldCache();
// 
// 	@Override
// 	boolean equals(Object obj);
// 
// 	@Override
// 	int hashCode();
// }
// 
// Path: src/main/java/com/github/worldsender/mcanm/common/skeleton/stored/RawData.java
// public class RawData implements ISkeletonVisitable {
// 	public static final long MAGIC_NUMBER = Utils.asciiToMagicNumber("MHFC SKL");
// 
// 	public static final RawData MISSING_DATA;
// 
// 	static {
// 		MISSING_DATA = new RawData();
// 		MISSING_DATA.modelUUID = new UUID(0, 0);
// 		MISSING_DATA.artist = "<unknown>";
// 		MISSING_DATA.specificData = new IVersionSpecificData() {
// 			@Override
// 			public void visitBy(ISkeletonVisitor visitor) {}
// 		};
// 	}
// 
// 	private static final ResourceCache<RawData> CACHE = new ResourceCache<>();
// 
// 	private static interface VersionizedModelLoader {
// 		IVersionSpecificData loadFrom(DataInputStream dis) throws IOException, ModelFormatException;
// 	}
// 
// 	private UUID modelUUID;
// 	private String artist;
// 	private IVersionSpecificData specificData;
// 
// 	private RawData() {}
// 
// 	@Override
// 	public void visitBy(ISkeletonVisitor visitor) {
// 		specificData.visitBy(visitor);
// 		visitor.visitEnd();
// 	}
// 
// 	public static RawData retrieveFrom(IResource resource) {
// 		return CACHE.getOrCompute(resource, r -> {
// 			try {
// 				return RawData.loadFrom(r);
// 			} catch (ModelFormatException mfe) {
// 				MCAnm.logger().error(String.format("Error loading skeleton from %s.", r.getResourceName()), mfe);
// 				return RawData.MISSING_DATA;
// 			}
// 		});
// 	}
// 
// 	private static RawData loadFrom(IResource resource) throws ModelFormatException {
// 		RawData data = new RawData();
// 		DataInputStream dis = resource.getInputStream();
// 
// 		try {
// 			long foundMagic = dis.readLong();
// 			if (foundMagic != MAGIC_NUMBER) {
// 				throw new ModelFormatException(
// 						String.format("Wrong MAGIC_NUMBER number. Found %x, expected %x.", foundMagic, MAGIC_NUMBER));
// 			}
// 
// 			data.modelUUID = new UUID(dis.readLong(), dis.readLong());
// 			data.artist = Utils.readString(dis);
// 			int version = dis.readInt();
// 			data.specificData = getLoaderForVersion(version).loadFrom(dis);
// 		} catch (EOFException eofe) {
// 			throw new ModelFormatException(
// 					String.format("Unexpected end of file (%s).", resource.getResourceName()),
// 					eofe);
// 		} catch (IOException ioe) {
// 			throw new ModelFormatException(
// 					String.format("Can't read from stream given (%s).", resource.getResourceName()),
// 					ioe);
// 		} catch (ModelFormatException mfe) {
// 			throw new ModelFormatException(
// 					String.format("Illegal Skeleton format in %s", resource.getResourceName()),
// 					mfe);
// 		}
// 		return data;
// 	}
// 
// 	private static VersionizedModelLoader getLoaderForVersion(int version) {
// 		switch (version) {
// 		case 1:
// 			return RawDataV1::loadFrom;
// 		default:
// 			break;
// 		}
// 		return o -> {
// 			throw new ModelFormatException("Unknown version: " + version);
// 		};
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "Skeleton[artist=" + artist + ", modelUUID=" + modelUUID + "]";
// 	}
// 
// }


import com.github.worldsender.mcanm.common.resource.IResourceLocation;
import com.github.worldsender.mcanm.common.skeleton.stored.RawData;
package com.github.worldsender.mcanm.common.skeleton;


public class SkeletonMCSKL extends AbstractSkeleton {
	public SkeletonMCSKL(IResourceLocation resLoc) {
// Path: src/main/java/com/github/worldsender/mcanm/common/resource/IResourceLocation.java
// public interface IResourceLocation {
// 	/**
// 	 * For data that has no definite location, this is suitable (e.g. one-time streams)
// 	 */
// 	public static final IResourceLocation UNKNOWN_LOCATION = new IResourceLocation() {
// 		@Override
// 		public IResource open() throws IOException {
// 			throw new NoSuchFileException("Unknown location");
// 		}
// 
// 		@Override
// 		public String getResourceName() {
// 			return "<unknown resource>";
// 		}
// 
// 		@Override
// 		public boolean shouldCache() {
// 			return false;
// 		}
// 
// 		@Override
// 		public void registerReloadListener(Consumer<IResourceLocation> reloadListener) {
// 			reloadListener.accept(this);
// 			// Don't store it, this location won't change
// 		}
// 	};
// 
// 	/**
// 	 * Opens the resource location described by this resource location.
// 	 * 
// 	 * @return an empty optional if the resource is currently (expectedly) absent
// 	 * @throws IOException
// 	 *             if the resource is absent unexpectedly
// 	 */
// 	IResource open() throws IOException;
// 
// 	/**
// 	 * Registers a listener that is being fired every time this resource changes. What "changes" means is deliberately
// 	 * left unspecified but a good example would be whenever the {@link Minecraft#getResourceManager()} changes, for
// 	 * example when a new resource pack is loaded.<br>
// 	 * <b>The initial stick is considered a change already, so this method should also fire the listener once.</b>
// 	 * 
// 	 * @param reloadListener
// 	 */
// 	void registerReloadListener(Consumer<IResourceLocation> reloadListener);
// 
// 	/**
// 	 * A descriptive name of the resource, perhaps the path
// 	 * 
// 	 * @return
// 	 */
// 	String getResourceName();
// 
// 	/**
// 	 * Returns false if this resource should not be cached, e.g. it is a one-time stream. When a
// 	 * {@link IResourceLocation} may get cached, {@link #open()} should succeed multiple times and return the same data
// 	 * every time, until the resource is reloaded.
// 	 * 
// 	 * @return
// 	 */
// 	boolean shouldCache();
// 
// 	@Override
// 	boolean equals(Object obj);
// 
// 	@Override
// 	int hashCode();
// }
// 
// Path: src/main/java/com/github/worldsender/mcanm/common/skeleton/stored/RawData.java
// public class RawData implements ISkeletonVisitable {
// 	public static final long MAGIC_NUMBER = Utils.asciiToMagicNumber("MHFC SKL");
// 
// 	public static final RawData MISSING_DATA;
// 
// 	static {
// 		MISSING_DATA = new RawData();
// 		MISSING_DATA.modelUUID = new UUID(0, 0);
// 		MISSING_DATA.artist = "<unknown>";
// 		MISSING_DATA.specificData = new IVersionSpecificData() {
// 			@Override
// 			public void visitBy(ISkeletonVisitor visitor) {}
// 		};
// 	}
// 
// 	private static final ResourceCache<RawData> CACHE = new ResourceCache<>();
// 
// 	private static interface VersionizedModelLoader {
// 		IVersionSpecificData loadFrom(DataInputStream dis) throws IOException, ModelFormatException;
// 	}
// 
// 	private UUID modelUUID;
// 	private String artist;
// 	private IVersionSpecificData specificData;
// 
// 	private RawData() {}
// 
// 	@Override
// 	public void visitBy(ISkeletonVisitor visitor) {
// 		specificData.visitBy(visitor);
// 		visitor.visitEnd();
// 	}
// 
// 	public static RawData retrieveFrom(IResource resource) {
// 		return CACHE.getOrCompute(resource, r -> {
// 			try {
// 				return RawData.loadFrom(r);
// 			} catch (ModelFormatException mfe) {
// 				MCAnm.logger().error(String.format("Error loading skeleton from %s.", r.getResourceName()), mfe);
// 				return RawData.MISSING_DATA;
// 			}
// 		});
// 	}
// 
// 	private static RawData loadFrom(IResource resource) throws ModelFormatException {
// 		RawData data = new RawData();
// 		DataInputStream dis = resource.getInputStream();
// 
// 		try {
// 			long foundMagic = dis.readLong();
// 			if (foundMagic != MAGIC_NUMBER) {
// 				throw new ModelFormatException(
// 						String.format("Wrong MAGIC_NUMBER number. Found %x, expected %x.", foundMagic, MAGIC_NUMBER));
// 			}
// 
// 			data.modelUUID = new UUID(dis.readLong(), dis.readLong());
// 			data.artist = Utils.readString(dis);
// 			int version = dis.readInt();
// 			data.specificData = getLoaderForVersion(version).loadFrom(dis);
// 		} catch (EOFException eofe) {
// 			throw new ModelFormatException(
// 					String.format("Unexpected end of file (%s).", resource.getResourceName()),
// 					eofe);
// 		} catch (IOException ioe) {
// 			throw new ModelFormatException(
// 					String.format("Can't read from stream given (%s).", resource.getResourceName()),
// 					ioe);
// 		} catch (ModelFormatException mfe) {
// 			throw new ModelFormatException(
// 					String.format("Illegal Skeleton format in %s", resource.getResourceName()),
// 					mfe);
// 		}
// 		return data;
// 	}
// 
// 	private static VersionizedModelLoader getLoaderForVersion(int version) {
// 		switch (version) {
// 		case 1:
// 			return RawDataV1::loadFrom;
// 		default:
// 			break;
// 		}
// 		return o -> {
// 			throw new ModelFormatException("Unknown version: " + version);
// 		};
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "Skeleton[artist=" + artist + ", modelUUID=" + modelUUID + "]";
// 	}
// 
// }


// Path: src/main/java/com/github/worldsender/mcanm/common/skeleton/SkeletonMCSKL.java
import com.github.worldsender.mcanm.common.resource.IResourceLocation;
import com.github.worldsender.mcanm.common.skeleton.stored.RawData;

package com.github.worldsender.mcanm.common.skeleton;


public class SkeletonMCSKL extends AbstractSkeleton {
	public SkeletonMCSKL(IResourceLocation resLoc) {
		super(resLoc, RawData::retrieveFrom);