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.func_98187_b("/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}