    001    package net.minecraft.client.gui;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.io.ByteArrayOutputStream;
    006    import java.io.DataOutputStream;
    007    import net.minecraft.entity.player.EntityPlayer;
    008    import net.minecraft.item.Item;
    009    import net.minecraft.item.ItemStack;
    010    import net.minecraft.nbt.NBTTagCompound;
    011    import net.minecraft.nbt.NBTTagList;
    012    import net.minecraft.nbt.NBTTagString;
    013    import net.minecraft.network.packet.Packet;
    014    import net.minecraft.network.packet.Packet250CustomPayload;
    015    import net.minecraft.util.ChatAllowedCharacters;
    016    import net.minecraft.util.StatCollector;
    017    import org.lwjgl.input.Keyboard;
    018    import org.lwjgl.opengl.GL11;
    019
    020    @SideOnly(Side.CLIENT)
    021    public 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.shiftedIndex;
    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    }