Thats correct.
Minecraft simply uploads the updated texture parts per glTexImage2d();
Here is a little code snippet that does the trick (Made by myself a year ago, still using it):
/**Updates an GLTexture with the given update Data. (Copys the given BufferedImage into the given texture at the given position.**/
public static void updateTexture(GLTexture texture,BufferedImage bufferedImage,int x,int y){
//Create Buffer
ByteBuffer imageData = ByteBuffer.allocateDirect(bufferedImage.getWidth() * bufferedImage.getHeight() * 4);
//Get values
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
//Setup moar Buffers
int rawPictureBuffer[] = new int[width * height];
byte outputPictureBuffer[] = new byte[width * height * 4];
//Put the Picture into the Raw Picture Buffer
bufferedImage.getRGB(0, 0, width, height, rawPictureBuffer, 0, width);
//Go trough the pictures RGBA data and copy it into the output buffer
for (int k = 0; k < rawPictureBuffer.length; k++)
{
//Get the Color Values
int i1 = rawPictureBuffer[k] >> 24 & 0xff;
int k1 = rawPictureBuffer[k] >> 16 & 0xff;
int i2 = rawPictureBuffer[k] >> 8 & 0xff;
int k2 = rawPictureBuffer[k] & 0xff;
//Put into Output Buffer
outputPictureBuffer[k * 4 + 0] = (byte)k1;
outputPictureBuffer[k * 4 + 1] = (byte)i2;
outputPictureBuffer[k * 4 + 2] = (byte)k2;
outputPictureBuffer[k * 4 + 3] = (byte)i1;
}
//Put the Output Buffer into the ByteBuffer
imageData.clear();
imageData.put(outputPictureBuffer);
imageData.position(0).limit(outputPictureBuffer.length);
texture.bind();
GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D,0,x,y,width,height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, imageData);
}
GLTexture is a very small class that i use to store textures.
Shouldn’t be hard to make your own version of it.
Also, this code is not the most performant, i did never optimize it because i never use that many animated-textures.
Have fun coding.
Edit:
Almost forgot: You can easely replace the BufferedImage with a ByteBuffer/Byte-Array/Integer-Array or something.