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 }