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