    001package net.minecraft.client.gui;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.io.ByteArrayOutputStream;
    006import java.io.DataOutputStream;
    007import net.minecraft.entity.player.EntityPlayer;
    008import net.minecraft.item.Item;
    009import net.minecraft.item.ItemStack;
    010import net.minecraft.nbt.NBTTagCompound;
    011import net.minecraft.nbt.NBTTagList;
    012import net.minecraft.nbt.NBTTagString;
    013import net.minecraft.network.packet.Packet;
    014import net.minecraft.network.packet.Packet250CustomPayload;
    015import net.minecraft.util.ChatAllowedCharacters;
    016import net.minecraft.util.StatCollector;
    017import org.lwjgl.input.Keyboard;
    018import org.lwjgl.opengl.GL11;
    019
    020@SideOnly(Side.CLIENT)
    021public class GuiScreenBook extends GuiScreen
    022{
    023    /** The player editing the book */
    024    private final EntityPlayer editingPlayer;
    025    private final ItemStack itemstackBook;
    026
    027    /** Whether the book is signed or can still be edited */
    028    private final boolean bookIsUnsigned;
    029    private boolean bookModified;
    030    private boolean editingTitle;
    031
    032    /** Update ticks since the gui was opened */
    033    private int updateCount;
    034    private int bookImageWidth = 192;
    035    private int bookImageHeight = 192;
    036    private int bookTotalPages = 1;
    037    private int currPage;
    038    private NBTTagList bookPages;
    039    private String bookTitle = "";
    040    private GuiButtonNextPage buttonNextPage;
    041    private GuiButtonNextPage buttonPreviousPage;
    042    private GuiButton buttonDone;
    043
    044    /** The GuiButton to sign this book. */
    045    private GuiButton buttonSign;
    046    private GuiButton buttonFinalize;
    047    private GuiButton buttonCancel;
    048
    049    public GuiScreenBook(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack, boolean par3)
    050    {
    051        this.editingPlayer = par1EntityPlayer;
    052        this.itemstackBook = par2ItemStack;
    053        this.bookIsUnsigned = par3;
    054
    055        if (par2ItemStack.hasTagCompound())
    056        {
    057            NBTTagCompound var4 = par2ItemStack.getTagCompound();
    058            this.bookPages = var4.getTagList("pages");
    059
    060            if (this.bookPages != null)
    061            {
    062                this.bookPages = (NBTTagList)this.bookPages.copy();
    063                this.bookTotalPages = this.bookPages.tagCount();
    064
    065                if (this.bookTotalPages < 1)
    066                {
    067                    this.bookTotalPages = 1;
    068                }
    069            }
    070        }
    071
    072        if (this.bookPages == null && par3)
    073        {
    074            this.bookPages = new NBTTagList("pages");
    075            this.bookPages.appendTag(new NBTTagString("1", ""));
    076            this.bookTotalPages = 1;
    077        }
    078    }
    079
    080    /**
    081     * Called from the main game loop to update the screen.
    082     */
    083    public void updateScreen()
    084    {
    085        super.updateScreen();
    086        ++this.updateCount;
    087    }
    088
    089    /**
    090     * Adds the buttons (and other controls) to the screen in question.
    091     */
    092    public void initGui()
    093    {
    094        this.controlList.clear();
    095        Keyboard.enableRepeatEvents(true);
    096
    097        if (this.bookIsUnsigned)
    098        {
    099            this.controlList.add(this.buttonSign = new GuiButton(3, this.width / 2 - 100, 4 + this.bookImageHeight, 98, 20, StatCollector.translateToLocal("book.signButton")));
    100            this.controlList.add(this.buttonDone = new GuiButton(0, this.width / 2 + 2, 4 + this.bookImageHeight, 98, 20, StatCollector.translateToLocal("gui.done")));
    101            this.controlList.add(this.buttonFinalize = new GuiButton(5, this.width / 2 - 100, 4 + this.bookImageHeight, 98, 20, StatCollector.translateToLocal("book.finalizeButton")));
    102            this.controlList.add(this.buttonCancel = new GuiButton(4, this.width / 2 + 2, 4 + this.bookImageHeight, 98, 20, StatCollector.translateToLocal("gui.cancel")));
    103        }
    104        else
    105        {
    106            this.controlList.add(this.buttonDone = new GuiButton(0, this.width / 2 - 100, 4 + this.bookImageHeight, 200, 20, StatCollector.translateToLocal("gui.done")));
    107        }
    108
    109        int var1 = (this.width - this.bookImageWidth) / 2;
    110        byte var2 = 2;
    111        this.controlList.add(this.buttonNextPage = new GuiButtonNextPage(1, var1 + 120, var2 + 154, true));
    112        this.controlList.add(this.buttonPreviousPage = new GuiButtonNextPage(2, var1 + 38, var2 + 154, false));
    113        this.updateButtons();
    114    }
    115
    116    /**
    117     * Called when the screen is unloaded. Used to disable keyboard repeat events
    118     */
    119    public void onGuiClosed()
    120    {
    121        Keyboard.enableRepeatEvents(false);
    122    }
    123
    124    private void updateButtons()
    125    {
    126        this.buttonNextPage.drawButton = !this.editingTitle && (this.currPage < this.bookTotalPages - 1 || this.bookIsUnsigned);
    127        this.buttonPreviousPage.drawButton = !this.editingTitle && this.currPage > 0;
    128        this.buttonDone.drawButton = !this.bookIsUnsigned || !this.editingTitle;
    129
    130        if (this.bookIsUnsigned)
    131        {
    132            this.buttonSign.drawButton = !this.editingTitle;
    133            this.buttonCancel.drawButton = this.editingTitle;
    134            this.buttonFinalize.drawButton = this.editingTitle;
    135            this.buttonFinalize.enabled = this.bookTitle.trim().length() > 0;
    136        }
    137    }
    138
    139    private void sendBookToServer(boolean par1)
    140    {
    141        if (this.bookIsUnsigned && this.bookModified)
    142        {
    143            if (this.bookPages != null)
    144            {
    145                while (this.bookPages.tagCount() > 1)
    146                {
    147                    NBTTagString var2 = (NBTTagString)this.bookPages.tagAt(this.bookPages.tagCount() - 1);
    148
    149                    if (var2.data != null && var2.data.length() != 0)
    150                    {
    151                        break;
    152                    }
    153
    154                    this.bookPages.removeTag(this.bookPages.tagCount() - 1);
    155                }
    156
    157                if (this.itemstackBook.hasTagCompound())
    158                {
    159                    NBTTagCompound var7 = this.itemstackBook.getTagCompound();
    160                    var7.setTag("pages", this.bookPages);
    161                }
    162                else
    163                {
    164                    this.itemstackBook.setTagInfo("pages", this.bookPages);
    165                }
    166
    167                String var8 = "MC|BEdit";
    168
    169                if (par1)
    170                {
    171                    var8 = "MC|BSign";
    172                    this.itemstackBook.setTagInfo("author", new NBTTagString("author", this.editingPlayer.username));
    173                    this.itemstackBook.setTagInfo("title", new NBTTagString("title", this.bookTitle.trim()));
    174                    this.itemstackBook.itemID = Item.writtenBook.itemID;
    175                }
    176
    177                ByteArrayOutputStream var3 = new ByteArrayOutputStream();
    178                DataOutputStream var4 = new DataOutputStream(var3);
    179
    180                try
    181                {
    182                    Packet.writeItemStack(this.itemstackBook, var4);
    183                    this.mc.getSendQueue().addToSendQueue(new Packet250CustomPayload(var8, var3.toByteArray()));
    184                }
    185                catch (Exception var6)
    186                {
    187                    var6.printStackTrace();
    188                }
    189            }
    190        }
    191    }
    192
    193    /**
    194     * Fired when a control is clicked. This is the equivalent of ActionListener.actionPerformed(ActionEvent e).
    195     */
    196    protected void actionPerformed(GuiButton par1GuiButton)
    197    {
    198        if (par1GuiButton.enabled)
    199        {
    200            if (par1GuiButton.id == 0)
    201            {
    202                this.mc.displayGuiScreen((GuiScreen)null);
    203                this.sendBookToServer(false);
    204            }
    205            else if (par1GuiButton.id == 3 && this.bookIsUnsigned)
    206            {
    207                this.editingTitle = true;
    208            }
    209            else if (par1GuiButton.id == 1)
    210            {
    211                if (this.currPage < this.bookTotalPages - 1)
    212                {
    213                    ++this.currPage;
    214                }
    215                else if (this.bookIsUnsigned)
    216                {
    217                    this.addNewPage();
    218
    219                    if (this.currPage < this.bookTotalPages - 1)
    220                    {
    221                        ++this.currPage;
    222                    }
    223                }
    224            }
    225            else if (par1GuiButton.id == 2)
    226            {
    227                if (this.currPage > 0)
    228                {
    229                    --this.currPage;
    230                }
    231            }
    232            else if (par1GuiButton.id == 5 && this.editingTitle)
    233            {
    234                this.sendBookToServer(true);
    235                this.mc.displayGuiScreen((GuiScreen)null);
    236            }
    237            else if (par1GuiButton.id == 4 && this.editingTitle)
    238            {
    239                this.editingTitle = false;
    240            }
    241
    242            this.updateButtons();
    243        }
    244    }
    245
    246    private void addNewPage()
    247    {
    248        if (this.bookPages != null && this.bookPages.tagCount() < 50)
    249        {
    250            this.bookPages.appendTag(new NBTTagString("" + (this.bookTotalPages + 1), ""));
    251            ++this.bookTotalPages;
    252            this.bookModified = true;
    253        }
    254    }
    255
    256    /**
    257     * Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e).
    258     */
    259    protected void keyTyped(char par1, int par2)
    260    {
    261        super.keyTyped(par1, par2);
    262
    263        if (this.bookIsUnsigned)
    264        {
    265            if (this.editingTitle)
    266            {
    267                this.func_74162_c(par1, par2);
    268            }
    269            else
    270            {
    271                this.keyTypedInBook(par1, par2);
    272            }
    273        }
    274    }
    275
    276    /**
    277     * Processes keystrokes when editing the text of a book
    278     */
    279    private void keyTypedInBook(char par1, int par2)
    280    {
    281        switch (par1)
    282        {
    283            case 22:
    284                this.func_74160_b(GuiScreen.getClipboardString());
    285                return;
    286            default:
    287                switch (par2)
    288                {
    289                    case 14:
    290                        String var3 = this.func_74158_i();
    291
    292                        if (var3.length() > 0)
    293                        {
    294                            this.func_74159_a(var3.substring(0, var3.length() - 1));
    295                        }
    296
    297                        return;
    298                    case 28:
    299                        this.func_74160_b("\n");
    300                        return;
    301                    default:
    302                        if (ChatAllowedCharacters.isAllowedCharacter(par1))
    303                        {
    304                            this.func_74160_b(Character.toString(par1));
    305                        }
    306                }
    307        }
    308    }
    309
    310    private void func_74162_c(char par1, int par2)
    311    {
    312        switch (par2)
    313        {
    314            case 14:
    315                if (this.bookTitle.length() > 0)
    316                {
    317                    this.bookTitle = this.bookTitle.substring(0, this.bookTitle.length() - 1);
    318                    this.updateButtons();
    319                }
    320
    321                return;
    322            case 28:
    323                if (this.bookTitle.length() > 0)
    324                {
    325                    this.sendBookToServer(true);
    326                    this.mc.displayGuiScreen((GuiScreen)null);
    327                }
    328
    329                return;
    330            default:
    331                if (this.bookTitle.length() < 16 && ChatAllowedCharacters.isAllowedCharacter(par1))
    332                {
    333                    this.bookTitle = this.bookTitle + Character.toString(par1);
    334                    this.updateButtons();
    335                    this.bookModified = true;
    336                }
    337        }
    338    }
    339
    340    private String func_74158_i()
    341    {
    342        if (this.bookPages != null && this.currPage >= 0 && this.currPage < this.bookPages.tagCount())
    343        {
    344            NBTTagString var1 = (NBTTagString)this.bookPages.tagAt(this.currPage);
    345            return var1.toString();
    346        }
    347        else
    348        {
    349            return "";
    350        }
    351    }
    352
    353    private void func_74159_a(String par1Str)
    354    {
    355        if (this.bookPages != null && this.currPage >= 0 && this.currPage < this.bookPages.tagCount())
    356        {
    357            NBTTagString var2 = (NBTTagString)this.bookPages.tagAt(this.currPage);
    358            var2.data = par1Str;
    359            this.bookModified = true;
    360        }
    361    }
    362
    363    private void func_74160_b(String par1Str)
    364    {
    365        String var2 = this.func_74158_i();
    366        String var3 = var2 + par1Str;
    367        int var4 = this.fontRenderer.splitStringWidth(var3 + "\u00a70_", 118);
    368
    369        if (var4 <= 118 && var3.length() < 256)
    370        {
    371            this.func_74159_a(var3);
    372        }
    373    }
    374
    375    /**
    376     * Draws the screen and all the components in it.
    377     */
    378    public void drawScreen(int par1, int par2, float par3)
    379    {
    380        int var4 = this.mc.renderEngine.getTexture("/gui/book.png");
    381        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    382        this.mc.renderEngine.bindTexture(var4);
    383        int var5 = (this.width - this.bookImageWidth) / 2;
    384        byte var6 = 2;
    385        this.drawTexturedModalRect(var5, var6, 0, 0, this.bookImageWidth, this.bookImageHeight);
    386        String var7;
    387        String var8;
    388        int var9;
    389
    390        if (this.editingTitle)
    391        {
    392            var7 = this.bookTitle;
    393
    394            if (this.bookIsUnsigned)
    395            {
    396                if (this.updateCount / 6 % 2 == 0)
    397                {
    398                    var7 = var7 + "\u00a70_";
    399                }
    400                else
    401                {
    402                    var7 = var7 + "\u00a77_";
    403                }
    404            }
    405
    406            var8 = StatCollector.translateToLocal("book.editTitle");
    407            var9 = this.fontRenderer.getStringWidth(var8);
    408            this.fontRenderer.drawString(var8, var5 + 36 + (116 - var9) / 2, var6 + 16 + 16, 0);
    409            int var10 = this.fontRenderer.getStringWidth(var7);
    410            this.fontRenderer.drawString(var7, var5 + 36 + (116 - var10) / 2, var6 + 48, 0);
    411            String var11 = String.format(StatCollector.translateToLocal("book.byAuthor"), new Object[] {this.editingPlayer.username});
    412            int var12 = this.fontRenderer.getStringWidth(var11);
    413            this.fontRenderer.drawString("\u00a78" + var11, var5 + 36 + (116 - var12) / 2, var6 + 48 + 10, 0);
    414            String var13 = StatCollector.translateToLocal("book.finalizeWarning");
    415            this.fontRenderer.drawSplitString(var13, var5 + 36, var6 + 80, 116, 0);
    416        }
    417        else
    418        {
    419            var7 = String.format(StatCollector.translateToLocal("book.pageIndicator"), new Object[] {Integer.valueOf(this.currPage + 1), Integer.valueOf(this.bookTotalPages)});
    420            var8 = "";
    421
    422            if (this.bookPages != null && this.currPage >= 0 && this.currPage < this.bookPages.tagCount())
    423            {
    424                NBTTagString var14 = (NBTTagString)this.bookPages.tagAt(this.currPage);
    425                var8 = var14.toString();
    426            }
    427
    428            if (this.bookIsUnsigned)
    429            {
    430                if (this.fontRenderer.getBidiFlag())
    431                {
    432                    var8 = var8 + "_";
    433                }
    434                else if (this.updateCount / 6 % 2 == 0)
    435                {
    436                    var8 = var8 + "\u00a70_";
    437                }
    438                else
    439                {
    440                    var8 = var8 + "\u00a77_";
    441                }
    442            }
    443
    444            var9 = this.fontRenderer.getStringWidth(var7);
    445            this.fontRenderer.drawString(var7, var5 - var9 + this.bookImageWidth - 44, var6 + 16, 0);
    446            this.fontRenderer.drawSplitString(var8, var5 + 36, var6 + 16 + 16, 116, 0);
    447        }
    448
    449        super.drawScreen(par1, par2, par3);
    450    }
    451}