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}