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