diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..3264ffe --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] " +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. Windows 11, Linux] + - Java version: [e.g. OpenJDK 1.8, 17] + - Minecraft version: [e.g. 1.8.8, 1.16.1] + - Plugin version: [e.g. 1.1, 1.2] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..11fc491 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/pom.xml b/pom.xml index 8881021..8645d27 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.codeboy mcide - 1.2-SNAPSHOT + 1.2.1 jar Mcide @@ -44,6 +44,18 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + org.junit.jupiter + junit-jupiter-engine + 5.2.0 + + + @@ -84,16 +96,10 @@ Piston4J v0.0.6 - - org.junit.jupiter - junit-jupiter - RELEASE - test - com.github.the-codeboy BukkitBootstrap - d663859a9d + f821d5e8d4 diff --git a/src/main/java/com/github/codeboy/mcide/Mcide.java b/src/main/java/com/github/codeboy/mcide/Mcide.java index cedbf64..9cfb8db 100644 --- a/src/main/java/com/github/codeboy/mcide/Mcide.java +++ b/src/main/java/com/github/codeboy/mcide/Mcide.java @@ -1,16 +1,20 @@ package com.github.codeboy.mcide; +import com.github.codeboy.mcide.commands.BoundItemCommand; import com.github.codeboy.mcide.commands.CreateProject; import com.github.codeboy.mcide.commands.IdeCommand; import com.github.codeboy.mcide.commands.RunCommand; import com.github.codeboy.mcide.config.Config; import com.github.codeboy.mcide.config.Message; +import com.github.codeboy.mcide.services.CustomItemEventManager; import com.github.codeboy.piston4j.api.ExecutionOutput; import com.github.codeboy.piston4j.api.ExecutionResult; import com.github.codeboy.piston4j.api.Piston; import com.google.gson.Gson; +import ml.codeboy.bukkitbootstrap.CustomItem; import ml.codeboy.bukkitbootstrap.config.ConfigReader; import org.bukkit.ChatColor; +import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.event.EventHandler; @@ -18,6 +22,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.java.JavaPlugin; +import javax.management.InstanceAlreadyExistsException; import java.io.File; import java.util.Arrays; import java.util.List; @@ -38,7 +43,6 @@ public static Piston getPiston() { @Override public void onEnable() { // Plugin startup logic - readConfigs(); piston = Piston.getInstance(Config.pistonEndPoint); @@ -47,6 +51,7 @@ public void onEnable() { getCommand("run").setExecutor(new RunCommand()); getCommand("ide").setExecutor(new IdeCommand()); getCommand("create-project").setExecutor(new CreateProject()); + getCommand("bound-item").setExecutor(new BoundItemCommand()); getServer().getPluginManager().registerEvents(new Listener() { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { @@ -54,6 +59,8 @@ public void onPlayerJoin(PlayerJoinEvent event) { } }, this); + getServer().getPluginManager().registerEvents(new CustomItemEventManager(), Mcide.getPlugin(Mcide.class)); + } private void readConfigs() { diff --git a/src/main/java/com/github/codeboy/mcide/commands/BoundItemCommand.java b/src/main/java/com/github/codeboy/mcide/commands/BoundItemCommand.java new file mode 100644 index 0000000..99660b7 --- /dev/null +++ b/src/main/java/com/github/codeboy/mcide/commands/BoundItemCommand.java @@ -0,0 +1,35 @@ +package com.github.codeboy.mcide.commands; + +import com.github.codeboy.mcide.config.Message; +import com.github.codeboy.mcide.ide.gui.ProjectSelector; +import com.github.codeboy.mcide.services.CustomItemEventManager; +import ml.codeboy.bukkitbootstrap.CustomItem; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.block.Action; + +public class BoundItemCommand implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + return false; + } + Player player = (Player) sender; + CustomItem customItem = CustomItem.createItemOrGet(player.getPlayerListName(), Material.GOLD_HOE, (short) 0); + player.getInventory().addItem(customItem.getItem()); + + CustomItemEventManager.addInteraction(customItem, event -> { + if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Player p = event.getPlayer(); + event.setCancelled(true); + ProjectSelector menu = new ProjectSelector(p); + menu.open(p); + event.setCancelled(true); + } + }); + return true; + } +} diff --git a/src/main/java/com/github/codeboy/mcide/config/Config.java b/src/main/java/com/github/codeboy/mcide/config/Config.java index 9cfa1fd..b837bb6 100644 --- a/src/main/java/com/github/codeboy/mcide/config/Config.java +++ b/src/main/java/com/github/codeboy/mcide/config/Config.java @@ -1,9 +1,12 @@ package com.github.codeboy.mcide.config; +import ml.codeboy.bukkitbootstrap.config.ConfigScope; import ml.codeboy.bukkitbootstrap.config.ConfigValue; +import ml.codeboy.bukkitbootstrap.config.Configurable; +@Configurable(name = "config.yml",comments = "Edit these values however you like\n" + + "They should be self explanatory",scope = ConfigScope.PUBLIC) public class Config { - @ConfigValue public static String language = "english"; @ConfigValue(key = "piston.endpoint") diff --git a/src/main/java/com/github/codeboy/mcide/config/Message.java b/src/main/java/com/github/codeboy/mcide/config/Message.java index a48f6bd..0f3d962 100644 --- a/src/main/java/com/github/codeboy/mcide/config/Message.java +++ b/src/main/java/com/github/codeboy/mcide/config/Message.java @@ -1,12 +1,18 @@ package com.github.codeboy.mcide.config; -import ml.codeboy.bukkitbootstrap.config.ConfigValue; +import ml.codeboy.bukkitbootstrap.config.ConfigScope; +import ml.codeboy.bukkitbootstrap.config.Configurable; import org.bukkit.ChatColor; +@Configurable(comments = "Edit these messages however you like\n" + + "It should be self explanatory where they are used",scope = ConfigScope.PUBLIC) public class Message { + // region CUSTOM_ITEM + public static String + ITEM_PROJECT_SELECTOR = "Open Menu"; + // endregion // region GUI - @ConfigValue public static String RUN_OPTION_TITLE = "Run options", RUN_CHAT_OPTION = "Chat output", @@ -15,7 +21,6 @@ public class Message { RUN_BOOK_OPTION_LORE = "Will redirect the output to written book"; // endregion // region info - @ConfigValue public static String PROJECTS = "projects", EXECUTION_START = ChatColor.BLUE + "Running project {0}", RIGHT_CLICK_TO_EDIT = ChatColor.BLUE + "Right click to edit. Move to cancel", @@ -26,7 +31,6 @@ public class Message { DELETE_FILE = ChatColor.RED + "delete file", EDIT_CANCELLED = ChatColor.DARK_RED + "Cancelled editing file {0}"; //region error - @ConfigValue public static String CMD_PLAYER_ONLY = ChatColor.RED + "Only players can use this command", LANGUAGE_AND_NAME_REQUIRED = ChatColor.RED + "You need to specify a language and a name for the project", NAME_REQUIRED = ChatColor.RED + "You need to specify a name!", @@ -34,7 +38,6 @@ public class Message { NOT_PROJECT_OWNER = ChatColor.RED + "You are not the owner of this project"; // endregion //region success - @ConfigValue public static String PROJECT_CREATE_SUCCESS = ChatColor.GREEN + "Project created successfully", RUN_PROJECT_SUCCESS = ChatColor.GREEN + "Ran project \"{0}\" successfully. Here is your output:", EDIT_SUCCESS = ChatColor.GREEN + "Edited file {0} successfully"; diff --git a/src/main/java/com/github/codeboy/mcide/ide/gui/ProjectMenu.java b/src/main/java/com/github/codeboy/mcide/ide/gui/ProjectMenu.java index 4f70204..3c87323 100644 --- a/src/main/java/com/github/codeboy/mcide/ide/gui/ProjectMenu.java +++ b/src/main/java/com/github/codeboy/mcide/ide/gui/ProjectMenu.java @@ -4,16 +4,17 @@ import com.github.codeboy.mcide.config.Message; import com.github.codeboy.mcide.ide.CodeProject; import com.github.codeboy.mcide.ide.MCCodeFile; +import ml.codeboy.bukkitbootstrap.gui.Action; import ml.codeboy.bukkitbootstrap.gui.Gui; import ml.codeboy.bukkitbootstrap.gui.MultiPageGui; import org.bukkit.Material; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; public class ProjectMenu extends MultiPageGui { private final CodeProject project; + private final int filesPerPage = 9 * 4; public ProjectMenu(CodeProject project) { super(Mcide.getPlugin(Mcide.class), 54, project.getTitle(), (Gui page) -> { @@ -43,29 +44,45 @@ protected int getPrevButtonIndex() { return 50; } + @Override + protected Gui createPage() { + Gui gui = super.createPage(); + ItemStack item = createItem(Material.STAINED_GLASS_PANE, "-"); + for (int i = 0; i < 9; i++) { + gui.addItem(item, 54 - 18 + i, Action.none); + } + return gui; + } + public void addFile(MCCodeFile file, boolean mainFile) { ItemStack fileItem = createItem(Material.BOOK_AND_QUILL, file.getName(), mainFile); - addItem(fileItem, p -> project.editFile(file, p)); + ArrayList pages = getPages(); + int index = 0; + Gui lastPage; + do { + lastPage = pages.get(index++); + } while (lastPage.getFreeSlot() > filesPerPage && index < pages.size()); + int freeSlot = lastPage.getFreeSlot(); + if (freeSlot > filesPerPage) { + addNextButton(lastPage); + lastPage = createPage(); + pages.add(lastPage); + addPrevButton(lastPage); + } + lastPage.addItem(fileItem, p -> project.editFile(file, p)); } public void removeFile() { - ArrayListpages=getPages(); - for (int i = pages.size() - 1; i >= 0; i--) { - Gui page=pages.get(i); - Inventory inventory= page.getInventory(); - - int index = inventory.getSize() - 1; - while (index>=0) { - if(isProjectFile(inventory.getItem(index))){ - inventory.setItem(index,null); - return; - } - index--; - } + int files = project.getMCCodeFiles().size(); + if (!project.getMCCodeFiles().get(files - 1).isMainFile()) { + int pageNumber = files / filesPerPage; + int slotNumber = files % filesPerPage; + Gui page = getPages().get(pageNumber); + page.removeItem(slotNumber); } } - private boolean isProjectFile(ItemStack itemStack){ - return itemStack!=null&&itemStack.getType()==Material.BOOK_AND_QUILL; + private boolean isProjectFile(ItemStack itemStack) { + return itemStack != null && itemStack.getType() == Material.BOOK_AND_QUILL; } } diff --git a/src/main/java/com/github/codeboy/mcide/services/CustomItemEventManager.java b/src/main/java/com/github/codeboy/mcide/services/CustomItemEventManager.java new file mode 100644 index 0000000..1057a9d --- /dev/null +++ b/src/main/java/com/github/codeboy/mcide/services/CustomItemEventManager.java @@ -0,0 +1,35 @@ +package com.github.codeboy.mcide.services; + +import ml.codeboy.bukkitbootstrap.CustomItem; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.function.Consumer; + +public class CustomItemEventManager implements Listener { + + private static final HashMap> interactions = new HashMap<>(); + + @EventHandler + public void onPlayerUse(PlayerInteractEvent event) { + Player player = event.getPlayer(); + ItemStack item = player.getItemInHand(); + for(CustomItem customItem:interactions.keySet()){ + if (customItem.itemIsInstance(item)) { + interactions.get(customItem).accept(event); + } + } + } + + public static boolean addInteraction(CustomItem customItem,Consumer interaction){ + if(interactions.containsKey(customItem)){ + return false; + } + interactions.put(customItem,interaction); + return true; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 50de563..03a3e95 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,4 +7,5 @@ website: https://github.com/the-codeboy commands: run: ide: - create-project: \ No newline at end of file + create-project: + bound-item: \ No newline at end of file diff --git a/src/test/java/com/github/codeboy/mcide/ide/MCCodeFileTest.java b/src/test/java/com/github/codeboy/mcide/ide/MCCodeFileTest.java new file mode 100644 index 0000000..a8ad13a --- /dev/null +++ b/src/test/java/com/github/codeboy/mcide/ide/MCCodeFileTest.java @@ -0,0 +1,102 @@ +package com.github.codeboy.mcide.ide; + +import com.github.codeboy.piston4j.api.CodeFile; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.*; + +public class MCCodeFileTest { + + private Random random; + + @Before + public void setUp() { + random = new Random(); + } + + private String randomString(int length) { + byte[] bytes = new byte[length]; + random.nextBytes(bytes); + return new String(bytes); + } + + @Test + public void getName() { + MCCodeFile codeFile = new MCCodeFile(); + assertEquals("Name of codefile without name should be \"unnamed\"", "unnamed", codeFile.getName()); + } + + @Test + public void setName() { + MCCodeFile codeFile = new MCCodeFile(); + String name = randomString(10); + + codeFile.setName(name); + + assertEquals("Name of codefile didn“t return correct name after setting it", name, codeFile.getName()); + } + + @Test + public void getContent() { + MCCodeFile codeFile = new MCCodeFile(); + String[] content = codeFile.getContent(); + + assertArrayEquals("Content should be empty by default", new String[0], content); + } + + @Test + public void setContent() { + MCCodeFile codeFile = new MCCodeFile(); + String[] expectedContent = {randomString(5), randomString(5)}; + codeFile.setContent(expectedContent); + + String[] content = codeFile.getContent(); + + assertArrayEquals("Content not the same after changing it", expectedContent,content); + } + + @Test + public void isMainFile() { + MCCodeFile codeFile = new MCCodeFile(); + assertFalse("Codefile should not be main file by default", codeFile.isMainFile()); + } + + @Test + public void setMainFile() { + MCCodeFile codeFile = new MCCodeFile(); + codeFile.setMainFile(true); + assertTrue("Codefile is not main file after setting it as main file", codeFile.isMainFile()); + } + + @Test + public void getProject() { + MCCodeFile codeFile = new MCCodeFile(); + assertNull("Project should be null by default", codeFile.getProject()); + } + + @Test + public void setProject() { + + } + + @Test + public void toCodeFile() { + MCCodeFile mcCodeFile = new MCCodeFile(); + + assertCodeFileEquals(mcCodeFile, mcCodeFile.toCodeFile()); + + mcCodeFile.setContent(randomString(15), randomString(20)); + + assertCodeFileEquals(mcCodeFile, mcCodeFile.toCodeFile()); + } + + private void assertCodeFileEquals(MCCodeFile mcCodeFile, CodeFile codeFile) { + assertNotNull("McCodeFile should not be null", mcCodeFile); + assertNotNull("CodeFile should not be null", codeFile); + + // no further tests because there currently CodeFile does not offer a way of accessing the content or name + } +} \ No newline at end of file