Jump to content

is it possible to dynamicly download a players face and use it on a gui?


mrgreaper

Recommended Posts

Ok with my problem block for the moment behind me, i started working on more fun stuff to be able to learn a bit more on GUI and NBT etc

 

What i would like to do is be able to download the Face texture of a player from a displayname (or any descriptor i need that i can save to an nbt) and display it on a gui (resized if needed)

 

The why... too long winded to put into text so i did a video (its just easier for me, and im sure many wont be fussed about the why...though im chuffed with what i achieved so far)

 

https://www.youtube.com/watch?v=Jk2C0GaadWQ

 

 

if you watched the video and want to know the code behind it

 

the item is

public class itemSecurityId extends twistedItems {

    //while learning nbt tags i came across a guide for keys, it gave me an idea for security ids, these will be used in two ways
    //1 on a secure alarmblock that will only shut off when right clicked with an authorized id card
    //2 a secure block that will stop emiting redstone only when right clicked with a authorized id card


    @Override //ok so when the item is created we make a nbt tag but not as i know it
    public void onCreated(ItemStack itemStack, World world, EntityPlayer player) {
        LogHelper.info("item created");
        makeNBT(itemStack, player); //lets make it a function so we can call it if theres not a tag:)
    }


    @Override
    public void addInformation(ItemStack itemStack, EntityPlayer player, 
                               List list, boolean par4) {
        if (itemStack.stackTagCompound != null) {
            String owner = itemStack.stackTagCompound.getString("user");
            String code = itemStack.stackTagCompound.getString("accessCode");
            list.add("Id Belongs to : " + owner);
            if (owner.equals(player.getDisplayName())) {
                list.add(EnumChatFormatting.GREEN + "Pass Code : " + code);
            } else {
                list.add(EnumChatFormatting.RED + "Pass Code : "
                        + EnumChatFormatting.OBFUSCATED + code);
            }
        }
    }

    @Override
    public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {
        LogHelper.info("security id right clicked");
        if (!player.isSneaking()) {
            if (itemStack.stackTagCompound != null) {
            } else {
                LogHelper.info("no tag compound lets make one");
                makeNBT(itemStack, player);
            }
        } else {
            if (itemStack.stackTagCompound != null) {
                FMLNetworkHandler.openGui(player, TwistedMod2.instance, BlockInfo.guiIDSecurityId, world, (int) player.posX, (int) player.posY, (int) player.posZ);

            } else {
                LogHelper.info("no tag compound lets make one");
                makeNBT(itemStack, player);
            }
        }
        return itemStack;
    }

    public void makeNBT(ItemStack itemStack, EntityPlayer player) {
        itemStack.stackTagCompound = new NBTTagCompound();
        itemStack.stackTagCompound.setString("user", player.getDisplayName()); //we get the username and set it as the string tag "user"
        itemStack.stackTagCompound.setString("accessCode", ReaperHelper.securityCode());//ok lets get a REALLY big number lol
    }


}

 

the Gui is

public class guiSecurityIdCard extends GuiScreen {

    private final EntityPlayer viewer;
    private final String accesscode;
    private final String username;

    ResourceLocation bground = new ResourceLocation(Reference.MODID + ":" + "textures/gui/SecurityId.png");

    public final int xSizeOfTexture = 220; //the width of your texture
    public final int ySizeOfTexture = 152;  //the height of our texture


    public guiSecurityIdCard(EntityPlayer player, String code, String user) { //hmmm really needed that to be the itemstack...gonna have to do some wierd stuff here
        this.viewer = player;
        this.accesscode = user;//yeah i got them the long way around and im being lazy
        this.username = code;
    }

    @Override
    public void drawScreen(int x, int y, float f) {
        drawDefaultBackground(); //draws default background (an overlay in the background)

        GL11.glColor4f(1f, 1f, 1f, 1f); //set the colour to black (yeah the method is missing a u but that seems common in minecraft 

        int posX = (this.width - xSizeOfTexture) / 2; //so we can center the gui on the screen
        int posY = (this.height - ySizeOfTexture) / 2;

        Minecraft.getMinecraft().getTextureManager().bindTexture(bground);
        drawTexturedModalRect(posX, posY, 0, 0, xSizeOfTexture, ySizeOfTexture);
        drawCenteredString(fontRendererObj, username, posX + 145 - username.length(), posY + 30, 0x0055cc);
        if (viewer.getDisplayName().equals(username)) {
            drawCenteredString(fontRendererObj, accesscode, posX + 155 - accesscode.length(), posY + 60, 0x66ff66);
        } else {
            drawCenteredString(fontRendererObj, EnumChatFormatting.OBFUSCATED + accesscode, posX + 155 - accesscode.length(), posY + 60, 0xee0000);
        }

        //above sets the background texture

        super.drawScreen(x, y, f);
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false; //dont pause the game
    }


}

 

my gui handler is (TBH i should pass on the itemstack and do the nbt checking inside the gui to allow better access to it)

 

public class GuiHandler implements IGuiHandler {


    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {//ok so if we are going to have gui on some items i need to not check to see if the tile entity is legit...after all it wont be in existence
        TileEntity entity = world.getTileEntity(x, y, z);
        switch (ID) {
            case BlockInfo.guiIDBunnyFurnace:
                LogHelper.info("gui choice....bunny furnace");
                if (entity instanceof TileEntityBunnyFurnace) {
                    return new ContainerBunnyFurnace(player.inventory, (TileEntityBunnyFurnace) entity);
                }
                return null;
            case BlockInfo.guiIDLivingBunny:
                LogHelper.info("gui choice....living bunny");
                return new ContainerLivingBunny(player);
            case BlockInfo.guiIDSecurityId:
                return new ContainerLivingBunny(player);
        }
        return null;
    }

    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { //ok so if we are going to have gui on some items i need to not check to see if the tile entity is legit...after all it wont be in existence
        TileEntity entity = world.getTileEntity(x, y, z);
        switch (ID) {
            case BlockInfo.guiIDBunnyFurnace:
                if (entity instanceof TileEntityBunnyFurnace) {
                    return new GuiBunnyFurnace(player.inventory, (TileEntityBunnyFurnace) entity);
                }
                return null;
            case BlockInfo.guiIDLivingBunny:
                return new GuiLivingBunny(player);
            case BlockInfo.guiIDSecurityId:
                return new guiSecurityIdCard(player, player.getCurrentEquippedItem().stackTagCompound.getString("user"), player.getCurrentEquippedItem().stackTagCompound.getString("accessCode"));
        }
        return null;
    }
}

 

it also has a standard container but no need to show that as its generic

 

if you look at the youtube video and want to use the code for your own open source mod, go for it, just if you fix any errors i have made let me know! and give me a nod in the credits

 

the github is at https://github.com/mrgreaper/TwistedMod2-reboot/

Link to comment
Share on other sites

public ResourceLocation getSkin(String name){
ResourceLocation resourcelocation = AbstractClientPlayer.locationStevePng;
            if (name.length() > 0)
            {
                resourcelocation = AbstractClientPlayer.getLocationSkin(name);
                AbstractClientPlayer.getDownloadImageSkin(resourcelocation, name);
            }
            return resourcelocation;
}

Link to comment
Share on other sites

public ResourceLocation getSkin(String name){
ResourceLocation resourcelocation = AbstractClientPlayer.locationStevePng;
            if (name.length() > 0)
            {
                resourcelocation = AbstractClientPlayer.getLocationSkin(name);
                AbstractClientPlayer.getDownloadImageSkin(resourcelocation, name);
            }
            return resourcelocation;
}

 

well this is the code i now have

 

package com.mrgreaper.twistedmod2.gui;

import com.mrgreaper.twistedmod2.handlers.ReaperHelper;
import com.mrgreaper.twistedmod2.reference.Reference;
import com.mrgreaper.twistedmod2.utility.LogHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;

/**
* Created by david on 10/07/2014.
*/
public class guiSecurityIdCard extends GuiScreen {

    private final EntityPlayer viewer;
    private final String accesscode;
    private String username;

    ResourceLocation bground = new ResourceLocation(Reference.MODID + ":" + "textures/gui/SecurityId.png");
    private ResourceLocation ownerface;



    public final int xSize = 220; //the width of your texture
    public final int ySize = 152;  //the height of our texture
    public final int faceXSize = 64; // the image we get for the face should always be the same size!
    public final int faceYsize=32;
    public final int faceStartX = 8; //where the face starts
    public final int faceStartY = 8;
    public final int faceOverlayStartX=40; //face is made of two parts
    public final int faceOverlayStartY=8;//not really needed as its ths same height as face start y but meh it keeps it neat
    private int guiLeft;
    private int guiTop;


    public guiSecurityIdCard(EntityPlayer player, String code, String user) { //hmmm really needed that to be the itemstack...gonna have to do some wierd stuff here
        this.viewer = player;
        this.accesscode = user;//yeah i got them the long way around and im being lazy
        this.username = code;
        this.ownerface = new ResourceLocation(ReaperHelper.getSkin(username)+"");
    }

    @Override
    public void drawScreen(int x, int y, float f) {
        drawDefaultBackground(); //draws default background (an overlay in the background)

        GL11.glColor4f(1f, 1f, 1f, 1f); //set the colour to black (yeah the method is missing a u but that seems common in minecraft 

        this.guiLeft = (this.width - this.xSize) / 2; //so we can center the gui on the screen
        this.guiTop = (this.height - this.ySize) / 2;

        Minecraft.getMinecraft().getTextureManager().bindTexture(bground);
        drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
        Minecraft.getMinecraft().getTextureManager().bindTexture(ownerface);
        drawTexturedModalRect(guiLeft+30,guiTop+25,faceStartX,faceStartY,8,;
        drawTexturedModalRect(guiLeft+30,guiTop+25,faceOverlayStartX,faceOverlayStartY,8,;
        drawCenteredString(fontRendererObj, username, guiLeft + 145 - username.length(), guiTop + 30, 0x0055cc);
        LogHelper.info(ReaperHelper.getSkin(username));
        if (viewer.getDisplayName().equals(username)) {
            drawCenteredString(fontRendererObj, accesscode, guiLeft + 155 - accesscode.length(), guiTop + 80, 0x66ff66);
        } else {
            drawCenteredString(fontRendererObj, EnumChatFormatting.OBFUSCATED + accesscode, guiLeft + 155 - accesscode.length(), guiTop + 80, 0xee0000);
        }

        //above sets the background texture

        super.drawScreen(x, y, f);
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false; //dont pause the game
    }


}

 

the method you gave me i put into a handler class as it may be useful for other stuff too

 

it gets the texture fine, in one test i made the whole gui background the skin so i could check it and it was there

 

now if im right the texture it gets is the same as this one http://s3.amazonaws.com/MinecraftSkins/mrgreaper.png (as the username im passing on to it is mrgreaper)

so that puts it at 64x32

with the face starting at 8,8 and being 8 across and 8 height

the overlay for the face (as it is actually two parts of the texture) starts at 40,8 and is also 8 across by 8 high.

 

so i bound those to variables (final as they should be the same for any skin download)

and

        Minecraft.getMinecraft().getTextureManager().bindTexture(ownerface);
        drawTexturedModalRect(guiLeft+30,guiTop+25,faceStartX,faceStartY,8,;
        drawTexturedModalRect(guiLeft+30,guiTop+25,faceOverlayStartX,faceOverlayStartY,8,;

 

should of placed first the face and then the overlay

 

 

but the result is this

 

SX8dQ.jpg

 

that little tiny square....ok so the size makes sense, need some way to make it bigger(is that possible) but what doesnt make sense is its not the right part of the skin, i checked using paint.net and it all seems to tally up, however earlier when i tried using a higher res image for the background it too went wrong (i ofcourse adjusted my  xSize and ySize) and indeed the only way to get the gui image to work right on this back ground was to adjust the xSize and zSize to a size beyond what it is (something wrong somewhere but)

 

any ideas?

Link to comment
Share on other sites

ok after a lot of searching i found a method that takes an image and draws it at the co-ordinates you specify at the size you request

//ok lets see x and y are the location of where the image will be placed, width and height are the size you want it ...zlevel?
public static void drawTexturedQuadFit(double x, double y, double width, double height, double zLevel){
        Tessellator tessellator = Tessellator.instance;
        tessellator.startDrawingQuads();
        tessellator.addVertexWithUV(x + 0, y + height, zLevel, 0,1);
        tessellator.addVertexWithUV(x + width, y + height, zLevel, 1, 1);
        tessellator.addVertexWithUV(x + width, y + 0, zLevel, 1,0);
        tessellator.addVertexWithUV(x + 0, y + 0, zLevel, 0, 0);
        tessellator.draw();
    }

 

but it draws the WHOLE texture

 

so heres my dilema i can have a tiny small part of the texture (not even the right part) OR have it the right size but all of the texture instead

 

 

i could cut a whole in the texture for the gui and have the skin render under it positioned right, but that just seems ...wrong

 

is there a way to tell this method to just use part of the texture?

 

i looked at the tessellator.class but cant see anything that would help

Link to comment
Share on other sites

 GL11.glPushMatrix();
            Minecraft.getMinecraft().renderEngine.bindTexture(yourfacelocation);
            GL11.glTranslatef(faceX, faceY, 0);
            float scale = 3F;
            GL11.glScalef(scale, scale, scale);
            drawTexturedModalRect(0, 0, 8, 8, 8, ; //correct if wrong
            GL11.glPopMatrix();

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



×
×
  • Create New...

Important Information

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