commit 1a356ec6bfc281ae188427691bb263b785ad1189 Author: 0xSeb Date: Fri Jun 26 18:10:09 2015 +0200 Test Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..41794ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.idea/ +.gradle/ +build/ +classes/ +eclipse/ +gradle/ +out/ +**/*.iml +*.txt +*.gradle +gradlew +gradlew.bat \ No newline at end of file diff --git a/src/main/java/de/skate702/craftingkeys/ContainerManager.java b/src/main/java/de/skate702/craftingkeys/ContainerManager.java new file mode 100644 index 0000000..bbb7690 --- /dev/null +++ b/src/main/java/de/skate702/craftingkeys/ContainerManager.java @@ -0,0 +1,271 @@ +package de.skate702.craftingkeys; + +import net.minecraft.client.gui.inventory.GuiCrafting; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +/** + * Managing Class to move Items in Inventory Containers. + * + * @author skate702 + * + */ +public class ContainerManager { + + /** + * The Container to work with. + */ + private Container container; + + public ContainerManager(Container container) { + + this.container = container; + + } + + /** + * Moves a full Stack from a slot to another. + * + * @param srcIndex + * The Source Slot Index of the Container + * @param destIndex + * The Destination Slot Index of the Container + */ + public void moveAll(int srcIndex, int destIndex) { + + ItemStack source = getItemStack(srcIndex); + + if (source == null) { + Helper.debugPrint("moveAll(): source == null"); + } else { + Helper.debugPrint("moveAll(): Redirected to move()"); + move(srcIndex, destIndex, source.stackSize); + } + + } + + /** + * Moves a specified amount of Items from a slot to another. [Based on + * INVTW] + * + * @param srcIndex + * The Source Slot Index of the Container + * @param destIndex + * The Destination Slot Index of the Container + * @param amount + * The amount of items to move (can be bigger then Stack Size) + */ + public void move(int srcIndex, int destIndex, int amount) { + + // Stacks + ItemStack source = getItemStack(srcIndex); + ItemStack destination = getItemStack(destIndex); + + // Same Location? + if (source == null || srcIndex == destIndex) { + Helper.debugPrint("Move(): srcIndex == destIndex OR source == null"); + return; + } + + // Test for max. moving Amount + int sourceSize = source.stackSize; + int movedAmount = Math.min(amount, sourceSize); + + // Move some + if (destination == null || source.isItemEqual(destination)) { + + leftClick(srcIndex); + for (int i = 0; i < movedAmount; i++) { + rightClick(destIndex); + } + + // Move back + if (movedAmount < sourceSize) { + leftClick(srcIndex); + } + + Helper.debugPrint("move(): Moved " + movedAmount + " from " + srcIndex + " to " + destIndex + "!"); + + } else { + Helper.debugPrint("Move(): Not the same block type!"); + } + + } + + /** + * Returns the ItemStack in a slot [Based on INVTW] + * + * @param index + * The index of the slot in the container + * @return Returns the ItemStack + */ + private ItemStack getItemStack(int index) { + + if (index >= 0 && index < container.inventorySlots.size()) { + + Slot slot = (Slot) (container.inventorySlots.get(index)); + return (slot == null) ? null : slot.getStack(); + + } else { + + Helper.debugPrint("getItemStack(): Invalid index"); + return null; + + } + + } + + /** + * Sends a click on the crafting output (craftingGUI or Inventory) + * + * @param isCraftingGUI + * true, if the craftingGUI is opened + */ + public void clickOnCraftingOutput(boolean isCraftingGUI) { + + putItemAway(isCraftingGUI); + + if (isCraftingGUI) { + + // Click on crafting output + Helper.debugPrint("clickOnCraftingOutput(): Clicked on Crafing Output."); + leftClick(0); + + } else { + // TODO: Same for inventory + } + + } + + /** + * Takes all items from a slot and moves them to the next empty slot or + * drops them. + * + * @param sourceIndex + * The index of the slot to move items from + * @param isCraftingGUI + * true, if the craftingGUI is opened + */ + public void putStackToNextEmptySlot(int sourceIndex, boolean isCraftingGUI, boolean isHeld) { + + // Check for Item-Type + ItemStack stackToMove; + if (isHeld) { + stackToMove = Helper.client.thePlayer.inventory.getItemStack(); + } else { + putItemAway(isCraftingGUI); + stackToMove = getItemStack(sourceIndex); + } + + // Test for empty crafting table slot + if (!isHeld && getItemStack(sourceIndex) == null) { + + Helper.debugPrint("putStackToNextEmptySlot(): No Item Stack @ " + sourceIndex + "."); + return; + } + + // Get Destination Index + int destIndex = getFirstPropperSlotIndex(isCraftingGUI, stackToMove); + + // Additional click on source index, if not held + if (!isHeld) { + leftClick(sourceIndex); + } + + // TODO: Optional (beta-like): Fill the items up. Let's become INVTW! + + // destIndex = -1 -> drop item + if (destIndex == -1) { + leftClick(-999); // Nice one, InvTweaks! + } else { + leftClick(destIndex); + } + + } + + private void putItemAway(boolean isCraftingGUI) { + // Put current Item away + if (Helper.client.thePlayer.inventory.getItemStack() != null) { + putStackToNextEmptySlot(-1, isCraftingGUI, true); + } + } + + /** + * Returns the first free index in a inventory + * + * @param isCraftingGUI + * true, if the craftingGUI is opened + * @return a slot index + */ + private int getFirstPropperSlotIndex(boolean isCraftingGUI, ItemStack movingItem) { + + if (isCraftingGUI) { + + for (int i = 10; i < container.inventorySlots.size(); i++) { + + if (getItemStack(i) != null) { + if (getItemStack(i).isItemEqual(movingItem)) { + if (getItemStack(i).stackSize + movingItem.stackSize <= movingItem.getMaxStackSize()) { + return i; + } + } + } + } + + for (int i = 10; i < container.inventorySlots.size(); i++) { + + if (getItemStack(i) == null) { + return i; + } + } + Helper.debugPrint("getFirstProperSlotIndex(): No Propper / Empty Slot found!"); + return -1; + } else { + // TODO: Same for inventory + return -1; + } + } + + /** + * Executes a left mouse click on a slot. [Based on INVTW] + * + * @param index + * The index of the slot in the container + */ + private void leftClick(int index) { + slotClick(index, false); + } + + /** + * Executes a right mouse click on a slot. [Based on INVTW] + * + * @param index + * The index of the slot in the container + */ + private void rightClick(int index) { + slotClick(index, true); + } + + /** + * Executes a mouse click on a slot. [Based on INVTW] + * + * @param index + * The index of the slot in the container + * @param rightClick + * True, if the click is with the right mouse button + */ + private void slotClick(int index, boolean rightClick) { + + Helper.debugPrint("slotClick(): Clicked @ Slot " + index + " with data " + rightClick + "."); + + int rightClickData = (rightClick) ? 1 : 0; + + CraftingKeys.instance.proxy.sendSlotClick(Helper.client.playerController, container.windowId, index, + rightClickData, 0, Helper.client.thePlayer); + + } + +} diff --git a/src/main/java/de/skate702/craftingkeys/CraftingKeys.java b/src/main/java/de/skate702/craftingkeys/CraftingKeys.java new file mode 100644 index 0000000..6aedb4d --- /dev/null +++ b/src/main/java/de/skate702/craftingkeys/CraftingKeys.java @@ -0,0 +1,174 @@ +package de.skate702.craftingkeys; + +import org.lwjgl.input.Keyboard; + +import net.minecraft.client.gui.inventory.GuiCrafting; +import net.minecraft.inventory.Slot; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.fml.common.FMLCommonHandler; +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.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import de.skate702.craftingkeys.proxies.CraftingKeysProxy; + +/** + * The Main Class of the Mod with the important onTick-Method. Some Methods are + * base on the open-source Inventory Tweaks. Big Thanks for that! + * + * @author skate702 + * + */ +@Mod(modid = "CraftingKeysID", name = "Crafting Keys", version = "1.0.0") +public class CraftingKeys { + + /** + * Current Instance of CraftingKeys. + */ + @Instance(value = "CraftingKeysID") + public static CraftingKeys instance; + + /** + * Current Proxy (Common or Client) + */ + @SidedProxy(clientSide = "de.skate702.craftingkeys.proxies.CraftingKeysClientProxy", serverSide = "de.skate702.craftingkeys.proxies.CraftingKeysProxy") + public static CraftingKeysProxy proxy; + + /** + * This method will be executed before Init. + * + * @param event + * Input Event from FML + */ + @EventHandler + public void preInit(FMLPreInitializationEvent event) { + } + + /** + * This method will be executed while loading. + * + * @param event + * Input Event from FML + */ + @EventHandler + public void load(FMLInitializationEvent event) { + + // Regeistring + proxy.registerRenderers(); + FMLCommonHandler.instance().bus().register(this); + + Helper.debugPrint("load(): Loaded CraftingKeys successful"); + + } + + /** + * This method will be executed after Init. + * + * @param event + * Input Event from FML + */ + @EventHandler + public void postInit(FMLPostInitializationEvent event) { + } + + /** + * To show a chat message at first start in minecraft. + */ + boolean firstInWorldTick = true; + + /** + * This method will be executed every Ingame Tick. + * + * @param tick + */ + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent tick) { + + // Message + if (Helper.client.theWorld != null && firstInWorldTick) { + + Helper.client.thePlayer.addChatMessage(new ChatComponentText( + "Achtung: Crafting-Keys befindet sich in der Pre-Alpha!")); + Helper.client.thePlayer.addChatMessage(new ChatComponentText( + "Es gibt noch viele Fehler, und es fehlen noch einige Funktionen.")); + Helper.client.thePlayer.addChatMessage(new ChatComponentText( + "Mehr Info's findest du auf: http://craftingkeys.codeplex.com!")); + + firstInWorldTick = !firstInWorldTick; + } + + // Case 1: Classic GUI Screen + if (Helper.isCraftingGUI(Helper.client.currentScreen)) { + + GuiCrafting guiCrafting = (GuiCrafting) Helper.client.currentScreen; + Slot currentHoveredSlot = Helper.getSlotAtMousePosition(guiCrafting); + int keyDown = Helper.craftingKeyDownToSlotNumber(); + + ContainerManager con = new ContainerManager(guiCrafting.inventorySlots); + + // Block Key Interval (avoid multiple Runs) + if (!Helper.isSameKey(keyDown)) { + + // Moving item to crafting table + if (keyDown > 0 && currentHoveredSlot != null) { + + // Shift = Move all + if (guiCrafting.isShiftKeyDown()) { + con.moveAll(currentHoveredSlot.slotNumber, keyDown); + } else { + con.move(currentHoveredSlot.slotNumber, keyDown, 1); + } + + } + + if (keyDown == -2) { + + // Space = Move all back + Helper.debugPrint("onTick(): Move all items back or drop them."); + + for (int i = 1; i < 10; i++) { + + con.putStackToNextEmptySlot(i, true, false); + + } + } + + // Strg = Take the output + if (guiCrafting.isCtrlKeyDown()) { + + if (guiCrafting.isShiftKeyDown()) { + + // Strg + Shift = Move all (resp. faster!) + con.clickOnCraftingOutput(true); + + } else { + + // Send mouse click on crafting output (accept also + // holding) + int ticksdown = Helper.getStrgTimesDown(true); + if (ticksdown == 2 || ticksdown % 15 == 0 || (ticksdown > 60 && ticksdown % 8 == 0)) { + con.clickOnCraftingOutput(true); + } + + } + + } else { + + // Reset Strg + Helper.getStrgTimesDown(false); + } + + } + } + + // Case 2: Inventory (2x2 Crafting, Quick-Armor) + + // TODO: Case 2 + + } +} diff --git a/src/main/java/de/skate702/craftingkeys/Helper.java b/src/main/java/de/skate702/craftingkeys/Helper.java new file mode 100644 index 0000000..a7c554c --- /dev/null +++ b/src/main/java/de/skate702/craftingkeys/Helper.java @@ -0,0 +1,226 @@ +package de.skate702.craftingkeys; + +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiCrafting; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; + +/** + * This helper class provides some static helping Methods and Constants. + * + * @author sebastian + * + */ +public class Helper { + + /** + * Private Constructor. This is a helping class! + */ + private Helper() { + // Nope. + } + + /** + * If true, there are Debug-Output-Prints from debugPrint(msg). + */ + public static final boolean DEBUG = true; + + /** + * Current Instance Client, used for a lot of operations. + */ + public static Minecraft client = FMLClientHandler.instance().getClient(); + + /** + * Standart Output for Debug-Messages - Depends on DEBUG-Constant. + * + * @param message + * The Debug-Message. Syntax: "methodname(): Message" + */ + public static void debugPrint(String message) { + + if (DEBUG) { + System.out.println("CK-DEBUG: " + message); + } + + } + + /** + * Returns true, if the current Screen is a instance of GUI-Screen. + * + * @param screen + * The input Screen + * @return True, if GuiScreen; False if null + */ + public static boolean isCraftingGUI(GuiScreen screen) { + + if (screen != null) { + if (screen instanceof GuiCrafting) { + return true; + } + } + return false; + } + + /** + * Returns the Slot at the current Mouse Position. [FROM GUICONTAINER] + * + * @param guiContainer + * The (Inventory) Container to work with. + * @return Returns the slot (or null) + */ + public static Slot getSlotAtMousePosition(GuiContainer guiContainer) { + if (guiContainer != null) { + Container container = guiContainer.inventorySlots; + + int x = getMouseX(guiContainer); + int y = getMouseY(guiContainer); + for (int k = 0; k < container.inventorySlots.size(); k++) { + Slot slot = (Slot) container.inventorySlots.get(k); + if (getIsMouseOverSlot(guiContainer, slot, x, y)) { + return slot; + } + } + return null; + } else { + Helper.debugPrint("getSlotAtMousePosition(): guiContainer == null"); + return null; + } + } + + /** + * Returns, if the mouse cursor is over a specified slot [FROM GUICONTAINER] + * + * @param guiContainer + * the GuiContainer to work with + * @param slot + * The spcified slot + * @param x + * The Mouse x-Position + * @param y + * The Mouse y-Position + * @return True, if the mouse is positioned over this slot. Otherwise false + */ + private static boolean getIsMouseOverSlot(GuiContainer guiContainer, Slot slot, int x, int y) { + if (guiContainer != null) { + + // Constants from Minecraft Source Code + x -= (guiContainer.width - 176) / 2; + y -= (guiContainer.height - 166) / 2; + return x >= slot.xDisplayPosition - 1 && x < slot.xDisplayPosition + 16 + 1 + && y >= slot.yDisplayPosition - 1 && y < slot.yDisplayPosition + 16 + 1; + } else { + return false; + } + } + + /** + * Returns a calculated Mouse Position for getSlotAtMousePosition(). + * + * @param guiContainer + * the GuiContainer to work with + * @return The relative Mouse-Position + */ + private static int getMouseX(GuiContainer guiContainer) { + return (Mouse.getEventX() * guiContainer.width) / client.displayWidth; + } + + /** + * Returns a calculated Mouse Position for getSlotAtMousePosition(). + * + * @param guiContainer + * the GuiContainer to work with + * @return The relative Mouse-Position + */ + private static int getMouseY(GuiContainer guiContainer) { + return guiContainer.height - (Mouse.getEventY() * guiContainer.height) / client.displayHeight - 1; + } + + /** + * Reads the current Keyboard-Input and converts it to a Inventory-Slot. + * + * @return A Inventory-Slot (based on CraftingGUI), -1 for wrong input, -2 + * for space + */ + public static int craftingKeyDownToSlotNumber() { + + // TODO: Make this dynamic! // Use Settings + + int returnValue = -1; + + if (Keyboard.isKeyDown(Keyboard.KEY_Q)) { + returnValue = 1; + } else if (Keyboard.isKeyDown(Keyboard.KEY_W)) { + returnValue = 2; + } else if (Keyboard.isKeyDown(Keyboard.KEY_E)) { + returnValue = 3; + } else if (Keyboard.isKeyDown(Keyboard.KEY_A)) { + returnValue = 4; + } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) { + returnValue = 5; + } else if (Keyboard.isKeyDown(Keyboard.KEY_D)) { + returnValue = 6; + } else if (Keyboard.isKeyDown(Keyboard.KEY_Y)) { + returnValue = 7; + } else if (Keyboard.isKeyDown(Keyboard.KEY_X)) { + returnValue = 8; + } else if (Keyboard.isKeyDown(Keyboard.KEY_C)) { + returnValue = 9; + } else if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) { + returnValue = -2; + } + + return returnValue; + } + + /** + * Saves the last Key that was Pressed + */ + private static int lastKeyDown = -1; + + /** + * Returns, if the current KeyValue is the same + * + * @param currentKey + * the new input value, saved in the method + * @return True, if these are the same keys + */ + public static boolean isSameKey(int currentKey) { + + boolean returnValue = false; + + if (lastKeyDown == currentKey && currentKey != -1) { + returnValue = true; + } + + lastKeyDown = currentKey; + return returnValue; + + } + + /** + * Saves the times strg was pressed before reseting + */ + private static int strgTimesDown = 0; + + /** + * Return the times Strg was pressed before reseting + * + * @param strgDown + * false, if reset + * @return A number of tick strg was down before + */ + public static int getStrgTimesDown(boolean strgDown) { + + if (!strgDown) + strgTimesDown = 0; + + return ++strgTimesDown; + + } +} diff --git a/src/main/java/de/skate702/craftingkeys/Settings.java b/src/main/java/de/skate702/craftingkeys/Settings.java new file mode 100644 index 0000000..122b088 --- /dev/null +++ b/src/main/java/de/skate702/craftingkeys/Settings.java @@ -0,0 +1,6 @@ +package de.skate702.craftingkeys; + +public class Settings { + +} + \ No newline at end of file diff --git a/src/main/java/de/skate702/craftingkeys/proxies/CraftingKeysClientProxy.java b/src/main/java/de/skate702/craftingkeys/proxies/CraftingKeysClientProxy.java new file mode 100644 index 0000000..b92677c --- /dev/null +++ b/src/main/java/de/skate702/craftingkeys/proxies/CraftingKeysClientProxy.java @@ -0,0 +1,30 @@ +package de.skate702.craftingkeys.proxies; + +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.entity.player.EntityPlayer; + +/** + * Client Proxy, extending Common Proxy. + * + * @author skate702 + * + */ +public class CraftingKeysClientProxy extends CraftingKeysProxy { + + @Override + public void registerRenderers() { + + } + + @Override + public void sendSlotClick(PlayerControllerMP controller, int windowId, int slot, int rightClick, int action, + EntityPlayer player) { + + // TODO: Make this *** multiplayer friendly + + controller.windowClick(windowId, slot, rightClick, action, player); + // player.openContainer.slotClick(slot, rightClick, action, player); + + } + +} diff --git a/src/main/java/de/skate702/craftingkeys/proxies/CraftingKeysProxy.java b/src/main/java/de/skate702/craftingkeys/proxies/CraftingKeysProxy.java new file mode 100644 index 0000000..b76b1fb --- /dev/null +++ b/src/main/java/de/skate702/craftingkeys/proxies/CraftingKeysProxy.java @@ -0,0 +1,45 @@ +package de.skate702.craftingkeys.proxies; + +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +/** + * The common proxy. + * + * @author skate702 + * + */ +public class CraftingKeysProxy { + + /** + * Register Renderers (not needed here). + */ + public void registerRenderers() { + + } + + /** + * The Minecraft call to send a mouse click to a GUI. [Based on INVTW] + * + * @param controller + * The playerController (from Client) + * @param windowId + * The current Windows ID (from GUI) + * @param slot + * The slot to click on (slot index) + * @param rightClick + * 1, if right click. Otherwise 0 + * @param action + * 0 + * @param player + * The current player (from Client) + */ + @SideOnly(Side.CLIENT) + public void sendSlotClick(PlayerControllerMP controller, int windowId, int slot, int rightClick, int action, + EntityPlayer player) { + + } + +} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..5001c10 --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "CraftingKeysID", + "name": "Crafting Keys", + "description": "TODO", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "http://skate702.de", + "updateUrl": "http://skate702.de", + "authorList": ["skate702"], + "credits": "Thanks to Inventory-Tweaks!", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +]