001    package net.minecraft.client.gui;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.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.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    }