Jump to content

[1.6.2] Creating and registering your own ResourcePack class


Akjosch

Recommended Posts

Ok, so I'm trying to do something which should be simple: Creating my own ResourcePack class. The currently available net.minecraft.client.resources.AbstractResourcePack just doesn't cut it for the following reasons (and I'd prefer to leave that alone so not to break anything else):

 

  • It's client-side only.
  • At least one of its implementations (FolderResourcePack) considers a directory to not be a valid resource (see: hasResourceName() checking for isFile()). Mind you, an archive file (which is basically the same thing: both are containers for resources) is accepted just fine, which is beyond silly.
  • There's no way to specify that your resource location is something with wildcards in it, or at least a filtered directory or archive.

 

Now, that's all fine. Implementing my own class which implements ResourcePack is easy enough. However, I have no way to tell that my mod wants to use this specific ResourcePack instead of the default FMLFolderResourcePack or FMLFileResourcePack (Or is there? I couldn't find it). At least not without changing the code of FMLModContainer's getCustomResourcePackClass() method, which means a coremod + ASM tricksery, which I loathe to do.

 

The other idea I had was to implement and inject my own ModContainer, derived from and almost identical to FMLModContainer, using (and triggered by) my own annotation instead of @cpw.mods.fml.common.Mod, but I still don't see how to achieve that. This time I get foiled, it seems, by ModContainerFactory's build() method, which has "@Mod" hardcoded as the only annotation it cares about. Again, only fixable by hacking around core Forge classes, not something I'm a fan of.

 

Do I really have to turn every single mod where I'd like to do something as trivial as use my own ResourcePack class into a coremod? Is there a better, more elegant method? My ideal solution would be a simple annotation alongside @Mod and @NetworkMod:

 

@ResourcePack(class="my.CustomResourcePack")

 

Side note: Tagged as 1.6.2 since that's what I'm using, but looking at the Forge code nothing much changed in 1.6.4 about my problems.

 

-------------------

Thinking about it a bit more, can I just modify Minecraft.getMinecraft().defaultResourcePacks (I know it's private ...) at some point before the last call to refreshResources(), or modify it and call the method myself, or will it horribly break things?

ItemBlock is not a Block

ItemStack is not an Item

Damage value is not metadata

 

Stop confusing them.

Link to comment
Share on other sites

I have no good replies for you, but I wanted to give you a heads up that there may be sever changes to the way such packs works in the upcoming 1.7 update.

 

For your last paragraph:

You can use Reflection to change a private member to public if that would help?

Else you could use a coremod and take advantage of the ASM library to modify the class at runtime (no direct base edits!)

 

 

 

If you guys dont get it.. then well ya.. try harder...

Link to comment
Share on other sites

I have no good replies for you, but I wanted to give you a heads up that there may be sever changes to the way such packs works in the upcoming 1.7 update.

 

Yeah ... would be nice to have it running for 1.6 though. Given how long some mods are taking to upgrade from 1.5 already, I'm not in a hurry.

 

You can use Reflection to change a private member to public if that would help?

Else you could use a coremod and take advantage of the ASM library to modify the class at runtime (no direct base edits!)

 

Forge already changes "private" class members to "public" at Minecraft startup (and before the mods load), so it works by simply changing them to "public" in your development environment and making sure you don't include anything which isn't in your packages when you make the distribution.

 

... and changing the functionality via ASM hacks is what I'm trying to avoid doing. ;)

ItemBlock is not a Block

ItemStack is not an Item

Damage value is not metadata

 

Stop confusing them.

Link to comment
Share on other sites

Personally, i would use

Minecraft.getMinecraft().mcResourcePackRepository.setRepositoryEntries(array);

to add a custom ResourcePackRepositoryEntry which override updateResourcePack() to call your custom ResourcePack.

 

As a side note, there is no "last call to refreshResources()". Minecraft itself does it regularly.

So you can do that anytime, i assume.

 

It's client-side only.

And how is that a drawback for a ResourcePack ? A server doesn't need multiple versions of the same thing...

Link to comment
Share on other sites

It's client-side only.

And how is that a drawback for a ResourcePack ? A server doesn't need multiple versions of the same thing...

 

Well yes, yes they do. Examples:

 

  • Localisation of server messages (depending on client's language setting)
  • Server-generated resources (again, depending on client's capabilities, localisation or settings)
  • Dynamically extending instead of replacing resources, which is the whole point of the exercise of having directories and wildcards as valid resource locations.

ItemBlock is not a Block

ItemStack is not an Item

Damage value is not metadata

 

Stop confusing them.

Link to comment
Share on other sites

Localisation handled by the server ?  :o

Are you crazy ?

This would mean different packet length for each receiving part depending on the receiver settings...this a f* nightmare !

Let that to client, please...

Or next time you are going to try handling the rendering on server side.:P

Link to comment
Share on other sites

Some test reports:

 

Well, hooking up my resource pack in FMLClientHandler.instance().resourcePackList and FMLClientHandler.instance().resourcePackMap in pre-init, followed by Minecraft.getMinecraft().refreshResources() works to a point - the FallbackResourceManager calls it up. However, it then tries to construct a SimpleResource, which needs an InputStream, which won't work and makes no sense with a directory.

 

Time to implement my own ResourceManager and convince Minecraft to use that for my mods ... Which will be kinda hard given it only uses one, in Minecraft.getMinecraft().mcResourceManager- Yay. Fun. Anybody got an easier, more straightforward idea?

 

ItemBlock is not a Block

ItemStack is not an Item

Damage value is not metadata

 

Stop confusing them.

Link to comment
Share on other sites

Test #2, time to implement my own InputStream which can deal with directories (and handles zip files as directories as well). Wish me luck. ;)

 

package my.package;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
* An InputStream supporting files and directories.
* <p>
* It works in one of several modes, depending on what the argument to the constructor was.
* <p>
* If the argument is a directory, it'll behave like a zero-length input stream. In addition,
* isDirectory() will return <i>true</i>, isFile() will return <i>false</i>. The specific files
* and directories are available through the default Iterable interface returned by
* the interface() method.
* <p>
* If the argument is an archive file (currently only ZIP files supported), it'll behave like
* a directory, but also allow for direct reading of the file same as a FileInputStream would
* and return <i>true</i> for isFile().
* <p>
* If the argument is any other file, this class behaves like a FileInputStream. In particular,
* iterator() returns <i>null</i>.
*/
public class DirectoryInputStream extends InputStream implements Iterable<InputStream>
{
private File baseFile = null;
private ZipFile zipFile = null;
private InputStream baseInputStream = null;

public DirectoryInputStream(String name) throws FileNotFoundException
{
	this(name != null ? new File(name) : null);
}

public DirectoryInputStream(File file) throws FileNotFoundException
{
	String name = (file != null ? file.getPath() : null);
        if (name == null) {
            throw new NullPointerException();
        }
        baseFile = file;
        try
        {
		zipFile = new ZipFile(file);
	}
        catch (ZipException ze)
        {
        	// This is clearly not a zip file. 
	}
        catch (IOException ioe)
        {
        	// Neither is this
	}
        if( baseFile.isFile() )
        {
        	baseInputStream = new FileInputStream(baseFile);
        }
   }

public boolean isFile()
{
	return baseFile.isFile();
}

public boolean isDirectory()
{
	return baseFile.isDirectory() || null != zipFile;
}

@Override
public int read() throws IOException
{
	return( null != baseInputStream ? baseInputStream.read() : -1 );
}

@Override
public int read(byte[] b) throws IOException
{
	return( null != baseInputStream ? baseInputStream.read(b) : -1 );
}

@Override
public int read(byte[] b, int off, int len) throws IOException
{
	return( null != baseInputStream ? baseInputStream.read(b, off, len) : -1);
}

@Override
public long skip(long n) throws IOException
{
	return( null != baseInputStream ? baseInputStream.skip(n) : 0);
}

@Override
public int available() throws IOException
{
	return( null != baseInputStream ? baseInputStream.available() : 0);
}

@Override
public void close() throws IOException
{
	if( null != baseInputStream )
	{
		baseInputStream.close();
	}
	if( null != zipFile )
	{
		zipFile.close();
	}
}

@Override
public synchronized void reset() throws IOException
{
	if( null != baseInputStream )
	{
		baseInputStream.reset();
	}
}

@Override
public Iterator<InputStream> iterator()
{
	if( baseFile.isDirectory() )
	{
		Iterator<InputStream> it = new Iterator<InputStream>()
		{
			private int currentIndex = 0;
			private File[] files = baseFile.listFiles();

			@Override
			public boolean hasNext()
			{
				return currentIndex + 1 < files.length;
			}

			@Override
			public InputStream next()
			{
				++ currentIndex;
				try {
					if( files[currentIndex].isDirectory() )
					{
						return new DirectoryInputStream(files[currentIndex]);
					}
					else
					{
						return new FileInputStream(files[currentIndex]);
					}
				}
				catch (FileNotFoundException e)
				{
					// Shouldn't happen
					return null;
				}
			}

			@Override
			public void remove()
			{
				// We don't supply remove()
			}
		};
		return it;
	}
	else if( null != zipFile )
	{
		// TODO: Make sure we don't accidentally return non-working InputStreams, like
		// for directories, and not crash and burn either when we encounter one.
		Iterator<InputStream> it = new Iterator<InputStream>()
		{
			private Enumeration<? extends ZipEntry> entries = zipFile.entries();

			@Override
			public boolean hasNext()
			{
				return entries.hasMoreElements();
			}

			@Override
			public InputStream next()
			{
				ZipEntry zipEntry = entries.nextElement();
				try
				{
					return zipFile.getInputStream(zipEntry);
				}
				catch (IOException e)
				{
					// Shouldn't happen. Did someone close the file on us?
					return null;
				}
			}

			@Override
			public void remove()
			{
				// We don't supply remove()
			}
		};
		return it;
	}
	else
	{
		return null;
	}
}

}

 

Input, as usual, very much appreciated.

ItemBlock is not a Block

ItemStack is not an Item

Damage value is not metadata

 

Stop confusing them.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Museumbola merupakan wadah judi online terkhusus untuk sbobet atau judi bola. Dengan daftar dan deposit menggunakan BANK BCA, Anda berkesempatan mendapatkan prediksi jitu pertandingan secara update setiap hari yang bisa anda jadikan acuan untuk bermain judi bola. Hanya dengan 10 ribu rupiah dan anda bermain Mix Parlay menggunakan prediksi yang telah di sediakan oleh kami, anda akan memenangkan jutaan rupiah. Yuk segera klik DAFTAR sekarang juga.
    • I was just trying to play my modded world when i randomly got this crash for no reason. I sorted through like every mod and eventually I realized it was LLibrary but I can't seem to find a solution to fix the crashing. I can't lose the world that I have that uses this mod please help me. Here's the report: https://pastebin.com/0D00B79i If anyone has a solution please let me know.  
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑   Daftar Slot Ligawin88 adalah bocoran slot rekomendasi gacor dari Ligawin88 yang bisa anda temukan di SLOT Ligawin88. Situs SLOT Ligawin88 hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Ligawin88 terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Ligawin88 merupakan SLOT Ligawin88 hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Ligawin88. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Ligawin88 hari ini yang telah disediakan SLOT Ligawin88. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Ligawin88 terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Ligawin88 terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Ligawin88 di link SLOT Ligawin88.
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑   Daftar Slot Asusslot adalah bocoran slot rekomendasi gacor dari Asusslot yang bisa anda temukan di SLOT Asusslot. Situs SLOT Asusslot hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Asusslot terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Asusslot merupakan SLOT Asusslot hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Asusslot. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Asusslot hari ini yang telah disediakan SLOT Asusslot. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Asusslot terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Asusslot terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Asusslot di link SLOT Asusslot.
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 Daftar Slot Galeri555 adalah bocoran slot rekomendasi gacor dari Galeri555 yang bisa anda temukan di SLOT Galeri555. Situs SLOT Galeri555 hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Galeri555 terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Galeri555 merupakan SLOT Galeri555 hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Galeri555. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Galeri555 hari ini yang telah disediakan SLOT Galeri555. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Galeri555 terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Galeri555 terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Galeri555 di link SLOT Galeri555.
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.