Markk Posted December 26, 2015 Share Posted December 26, 2015 I want to modify the vanilla note block so that when a player right clicks it, a GUI opens (rather than tuning it.) However, I have not been successful. Main class with the initiation methods: package com.mark.nbgui; import net.minecraft.block.BlockNote; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; @Mod(modid = NBGUI.MODID, version = NBGUI.VERSION, name = NBGUI.NAME, dependencies=NBGUI.DEPENDENCIES) public class NBGUI { public static final String MODID = "NBGUI"; public static final String VERSION = "1.0"; public static final String NAME = "Note Block GUI"; public static final String DEPENDENCIES = "required-after:FML"; public static final BlockNote BlockNote = new BlockNote(); public static final NoteBlock NoteBlock = new NoteBlock(); @Instance("NBGUI") public static NBGUI instance; @SidedProxy(modId = "NBGUI",clientSide = "com.mark.nbgui.ClientProxy", serverSide = "com.mark.nbgui.CommonProxy") public static CommonProxy proxy; @EventHandler public void preInit(FMLPreInitializationEvent event) { } @EventHandler public void init(FMLInitializationEvent event) { NetworkRegistry.INSTANCE.registerGuiHandler(NBGUI.instance, new GUIHandler()); } @EventHandler public void postInit(FMLPostInitializationEvent event) { } } Client and Common proxies are empty. GUI class: package com.mark.nbgui; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class GUI extends GuiScreen { public final static int GUI_ID = 20; private final int bookImageHeight = 192; private final int bookImageWidth = 192; private int currPage = 0; private static final int bookTotalPages = 4; private static ResourceLocation[] bookPageTextures = new ResourceLocation[bookTotalPages]; private static String[] stringPageText = new String[bookTotalPages]; private GuiButton buttonDone; private NextPageButton buttonNextPage; private NextPageButton buttonPreviousPage; public void StringGUI() { bookPageTextures[0] = new ResourceLocation(NBGUI.MODID+":textures/gui/book_cover.png"); bookPageTextures[1] = new ResourceLocation(NBGUI.MODID+":textures/gui/book.png"); bookPageTextures[2] = new ResourceLocation(NBGUI.MODID+":textures/gui/book.png"); stringPageText[0] = ""; stringPageText[1] = "The Mysterious Stranger admired your family cow and asked if it was for sale.\n\nWhen you nodded, he offered to trade some Magic Beans, that (if planted in tilled dirt) would lead to more wealth than you could imagine."; stringPageText[2]="So you handed him your cow, and grabbed the Magic Beans.\n\nPleased with yourself, you hurried away, looking for tilled dirt in which to plant the Magic Beans.\n\nYou couldn't wait to see how proud your mother would be for"; stringPageText[3]="being so shrewd! Untold wealth in return for an old, milkless cow; what a good deal you made!\n\nSo off you went, looking for a place to plant the Magic Beans with room to grow..."; } /** * Adds the buttons (and other controls) to the screen in question. */ @Override public void initGui() { // DEBUG System.out.println("GuiMysteriousStranger initGUI()"); buttonList.clear(); Keyboard.enableRepeatEvents(true); buttonDone = new GuiButton(0, width / 2 + 2, 4 + bookImageHeight, 98, 20, I18n.format("gui.done", new Object[0])); buttonList.add(buttonDone); int offsetFromScreenLeft = (width - bookImageWidth) / 2; buttonList.add(buttonNextPage = new NextPageButton(1, offsetFromScreenLeft + 120, 156, true)); buttonList.add(buttonPreviousPage = new NextPageButton(2, offsetFromScreenLeft + 38, 156, false)); } /** * Called from the main game loop to update the screen. */ @Override public void updateScreen() { buttonDone.visible = (currPage == bookTotalPages - 1); buttonNextPage.visible = (currPage < bookTotalPages - 1); buttonPreviousPage.visible = currPage > 0; } /** * Draws the screen and all the components in it. */ @Override public void drawScreen(int parWidth, int parHeight, float p_73863_3_) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); if (currPage == 0) { mc.getTextureManager().bindTexture(bookPageTextures[0]); } else { mc.getTextureManager().bindTexture(bookPageTextures[1]); } int offsetFromScreenLeft = (width - bookImageWidth ) / 2; drawTexturedModalRect(offsetFromScreenLeft, 2, 0, 0, bookImageWidth, bookImageHeight); int widthOfString; String stringPageIndicator = I18n.format("book.pageIndicator", new Object[] {Integer.valueOf(currPage + 1), bookTotalPages}); widthOfString = fontRendererObj.getStringWidth(stringPageIndicator); fontRendererObj.drawString(stringPageIndicator, offsetFromScreenLeft - widthOfString + bookImageWidth - 44, 18, 0); fontRendererObj.drawSplitString(stringPageText[currPage], offsetFromScreenLeft + 36, 34, 116, 0); super.drawScreen(parWidth, parHeight, p_73863_3_); } /** * Called when a mouse button is pressed and the mouse is moved around. * Parameters are : mouseX, mouseY, lastButtonClicked & * timeSinceMouseClick. */ @Override protected void mouseClickMove(int parMouseX, int parMouseY, int parLastButtonClicked, long parTimeSinceMouseClick) { } @Override protected void actionPerformed(GuiButton parButton) { if (parButton == buttonDone) { // You can send a packet to server here if you need server to do // something mc.displayGuiScreen((GuiScreen)null); } else if (parButton == buttonNextPage) { if (currPage < bookTotalPages - 1) { ++currPage; } } else if (parButton == buttonPreviousPage) { if (currPage > 0) { --currPage; } } } /** * Called when the screen is unloaded. Used to disable keyboard repeat * events */ @Override public void onGuiClosed() { } /** * Returns true if this GUI should pause the game when it is displayed in * single-player */ @Override public boolean doesGuiPauseGame() { return true; } @SideOnly(Side.CLIENT) static class NextPageButton extends GuiButton { private final boolean isNextButton; public NextPageButton(int parButtonId, int parPosX, int parPosY, boolean parIsNextButton) { super(parButtonId, parPosX, parPosY, 23, 13, ""); isNextButton = parIsNextButton; } /** * Draws this button to the screen. */ @Override public void drawButton(Minecraft mc, int parX, int parY) { if (visible) { boolean isButtonPressed = (parX >= xPosition && parY >= yPosition && parX < xPosition + width && parY < yPosition + height); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); mc.getTextureManager().bindTexture(bookPageTextures[1]); int textureX = 0; int textureY = 192; if (isButtonPressed) { textureX += 23; } if (!isNextButton) { textureY += 13; } drawTexturedModalRect(xPosition, yPosition, textureX, textureY, 23, 13); } } } } GUI Handler: package com.mark.nbgui; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.network.IGuiHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class GUIHandler implements IGuiHandler { @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { if (ID == GUI.GUI_ID) { return new GUI(); } return null; } } Class that overrides onBlockActivated for the note block. package com.mark.nbgui; import net.minecraft.block.BlockNote; import net.minecraft.block.state.IBlockState; import net.minecraft.util.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; public class NoteBlock extends BlockNote { @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { if (!worldIn.isRemote) { playerIn.openGui(NBGUI.instance, GUI.GUI_ID, worldIn, 10, 10, 10); } return true; } } I followed these two tutorials: http://www.minecraftforge.net/wiki/Basic_GUI http://jabelarminecraft.blogspot.com/p/minecraft-modding-block-with-simple-gui.html (the GUI class was copied from this tutorial.) http://jabelarminecraft.blogspot.com/p/minecraft-modding-containers.html (didn't copy any code, just read for information.) I first tried following the second tutorial fully, but the interface didn't open. I thought that since the note block is a block that extends BlockContainer, perhaps I need to make a GuiHandler and use openGui() instead to open the interface. This didn't work either. I think it may be because I haven't properly made an instance of the block in my main class. I attempted to with public static final BlockNote BlockNote = new BlockNote(); public static final NoteBlock NoteBlock = new NoteBlock(); , first for my own class and then also with the vanilla class. Also, if I used EntityPlayer.openGui rather than playerIn.openGui (I'm not even sure what the difference is), I would get an error saying that I can't make a static reference to a non-static method. Lastly, I had no idea what to put for the integer arguments, so I just put in 10. Where did I go wrong? How can I fix this? I'm new to Java and this is my first mod, so excuse any blatant faults with the code. Quote Link to comment Share on other sites More sharing options...
Markk Posted December 26, 2015 Author Share Posted December 26, 2015 Dude, just use PlayerInteractEvent. So, something like this? public void openGUI(PlayerInteractEvent event) { if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK){ EntityPlayer.openGui(); } } I'm still not sure which arguments to put into openGui. Also, how do I specify which block the player has to interact with to trigger openGui? Quote Link to comment Share on other sites More sharing options...
Markk Posted December 26, 2015 Author Share Posted December 26, 2015 You get the Block from the world and coordinates given in the event and check if it's the one you want. I've figured out how to get the block, but now I need to figure out how to check if it's the right block. I don't know if getBlock returns an ID or a name and how it will be formatted, so I've made some prints to help me figure this out and just see if what I have so far works. However, when I right click any block, nothing is printed to the console. public void openGUI(PlayerInteractEvent event) { if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK){ World world = event.world; Block block = world.getBlockState(event.pos).getBlock(); //EntityPlayer.openGui(NBGUI.instance, GUI_ID, world, event.pos.getX(), event.pos.getY(), event.pos.getZ()); //DEBUG System.out.println("Position:" +event.pos); System.out.println("Block:" +block); } } Quote Link to comment Share on other sites More sharing options...
Markk Posted December 26, 2015 Author Share Posted December 26, 2015 Ah, no I did not put @SubscribeEvent. I also never made an event handler. I guess I should look that up now. Also, still not sure about openGui. Are the integers supposed to be the block position? I put in the event position (which I'm assuming is the position of the block rather than of the player when the event happens), but I get an error saying "Cannot make a static reference to the non-static method openGui(Object, int, World, int, int, int) from the type EntityPlayer." Edit: Do I make this event in the client or common event handler? Quote Link to comment Share on other sites More sharing options...
Markk Posted December 26, 2015 Author Share Posted December 26, 2015 You can pass in whatever numbers you want. Your IGuiHandler is responsible for interpreting them correctly. As for the error message, it is pretty obvious if you know basic Java, which you should. Okay, I've figured it out. However, for some reason, my my debug prints occur twice in the console: [22:26:35] [Client thread/INFO] [sTDOUT]: [com.mark.nbgui.EventHandlerCommon:openGUI:23]: POS: BlockPos{x=-256, y=64, z=119} [22:26:35] [Client thread/INFO] [sTDOUT]: [com.mark.nbgui.EventHandlerCommon:openGUI:24]: BLOCK: Block{minecraft:noteblock} Block{minecraft:noteblock} [22:26:35] [server thread/INFO]: Saving and pausing game... [22:26:35] [server thread/INFO]: Saving chunks for level 'New World'/Overworld [22:26:35] [server thread/INFO]: Saving chunks for level 'New World'/Nether [22:26:35] [server thread/INFO]: Saving chunks for level 'New World'/The End [22:26:35] [server thread/INFO] [sTDOUT]: [com.mark.nbgui.EventHandlerCommon:openGUI:23]: POS: BlockPos{x=-256, y=64, z=119} [22:26:35] [server thread/INFO] [sTDOUT]: [com.mark.nbgui.EventHandlerCommon:openGUI:24]: BLOCK: Block{minecraft:noteblock} Block{minecraft:noteblock} Here is my code: @SubscribeEvent public void openGUI(PlayerInteractEvent event) { if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK){ World world = event.world; Block block = world.getBlockState(event.pos).getBlock(); String blocktype = block.toString(); EntityPlayer player = event.entityPlayer; if (blocktype.equals("Block{minecraft:noteblock}")) { player.openGui(NBGUI.instance, GUI.GUI_ID, world, event.pos.getX(), event.pos.getY(), event.pos.getZ()); } //DEBUG System.out.println("POS: " +event.pos); System.out.println("BLOCK: " +block); System.out.print(blocktype); } } } Is this normal/something I can ignore, or is it a sign that something is wrong (presumably with my event handler)? Quote Link to comment Share on other sites More sharing options...
Choonster Posted December 26, 2015 Share Posted December 26, 2015 Okay, I've figured it out. However, for some reason, my my debug prints occur twice in the console: If you look carefully, you'll notice that it's being printed once from the client thread and once from the server thread. ... Block block = world.getBlockState(event.pos).getBlock(); String blocktype = block.toString(); EntityPlayer player = event.entityPlayer; if (blocktype.equals("Block{minecraft:noteblock}")) { ... There is almost never a good reason to use the output of toString for anything but log/exception messages. In this case, you should compare block directly to the Note Block instance ( Blocks.noteblock ) using the equality ( == ) operator. If they're the equal (i.e. the same object), the block is a Note Block. Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future. Link to comment Share on other sites More sharing options...
Markk Posted December 26, 2015 Author Share Posted December 26, 2015 Okay, I've figured it out. However, for some reason, my my debug prints occur twice in the console: If you look carefully, you'll notice that it's being printed once from the client thread and once from the server thread. ... Block block = world.getBlockState(event.pos).getBlock(); String blocktype = block.toString(); EntityPlayer player = event.entityPlayer; if (blocktype.equals("Block{minecraft:noteblock}")) { ... There is almost never a good reason to use the output of toString for anything but log/exception messages. In this case, you should compare block directly to the Note Block instance ( Blocks.noteblock ) using the equality ( == ) operator. If they're the equal (i.e. the same object), the block is a Note Block. Ah okay, I can't believe I didn't notice it was server and client outputs together. I thought the doubling had something to do with the note block tuning up twice in a laggy manner when I right click it. I don't know why that happens or if it will be in issue later (because I plan to remove the original right click functionality.) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.