{"id":22491759,"url":"https://github.com/mrnemo64/better-inputs","last_synced_at":"2025-08-03T00:31:09.086Z","repository":{"id":45621437,"uuid":"506975403","full_name":"MrNemo64/better-inputs","owner":"MrNemo64","description":"A Java API to easily get input from users","archived":false,"fork":false,"pushed_at":"2024-06-14T21:20:07.000Z","size":857,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-22T22:43:55.207Z","etag":null,"topics":["java","minecraft","spigot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MrNemo64.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-24T10:50:42.000Z","updated_at":"2024-06-14T21:18:51.000Z","dependencies_parsed_at":"2024-02-26T20:24:41.824Z","dependency_job_id":"753824c3-c757-4544-8579-dde83021e0ca","html_url":"https://github.com/MrNemo64/better-inputs","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrNemo64%2Fbetter-inputs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrNemo64%2Fbetter-inputs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrNemo64%2Fbetter-inputs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrNemo64%2Fbetter-inputs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MrNemo64","download_url":"https://codeload.github.com/MrNemo64/better-inputs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228508031,"owners_count":17931263,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","minecraft","spigot"],"created_at":"2024-12-06T18:10:11.188Z","updated_at":"2024-12-06T18:10:11.829Z","avatar_url":"https://github.com/MrNemo64.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Contributors][contributors-shield]][contributors-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![GPLv3 License][license-shield]][license-url]\n\n\n\n\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/MrNemo64/better-inputs\"\u003e\n    \u003cimg src=\"images/icon.png\" alt=\"Logo\" width=\"128\" height=\"128\"/\u003e\n  \u003c/a\u003e\n\n  \u003ch3 align=\"center\"\u003eBetterInputs\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    \u003c!-- TODO: project_description --\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://mrnemo64.github.io/better-inputs/javadoc\"\u003e\u003cstrong\u003eExplore the docs »\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/MrNemo64/better-inputs/issues/new\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/MrNemo64/better-inputs/issues/new\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\u003cdetails open=\"open\"\u003e\n  \u003csummary\u003e\u003ch2 style=\"display: inline-block\"\u003eTable of Contents\u003c/h2\u003e\u003c/summary\u003e\n  \u003col\u003e\n    \u003cli\u003e\n      \u003ca href=\"#about-the-project\"\u003eAbout The Project\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#built-with\"\u003eBuilt With\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#getting-started\"\u003eGetting Started\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\n          \u003ca href=\"#setup\"\u003eSetup\u003c/a\u003e\n          \u003cul\u003e\n            \u003cli\u003e\u003ca href=\"#maven\"\u003eMaven\u003c/a\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\n          \u003cul\u003e\n            \u003cli\u003e\u003ca href=\"#using-the-api-to-get-input\"\u003eUsing the api to get input\u003c/a\u003e\u003c/li\u003e\n            \u003cli\u003e\u003ca href=\"#using-the-api-to-provide-input\"\u003eUsing the api to provide input\u003c/a\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#roadmap\"\u003eRoadmap\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#contact\"\u003eContact\u003c/a\u003e\u003c/li\u003e\n  \u003c/ol\u003e\n\u003c/details\u003e\n\n\n\n\u003c!-- ABOUT THE PROJECT --\u003e\n## About The Project\n\n\u003c!-- \u003cimg src=\"images/banner.png\" alt=\"BetterInputs Banner\"/\u003e --\u003e\nAiming to make getting input from users easier, better inputs tries to provide a collection of classes to get input from users. With this API we hope that getting input from an user can be as easy as creating a simple command.\n\n### Built With\n\n* [Spigot](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/browse)\n* [LayLib](https://github.com/Lauriichan/LayLib)\n\n\n\u003c!-- GETTING STARTED --\u003e\n## Getting Started\n\nTo get a local copy you only need to download it from [Spigot](https://www.spigotmc.org/resources/betterinputs.106010/)\nor if you want to get the Source just fork this repository or download it as zip.\n\n### Installation\n\nTo install the plugin you only need to do following steps:\n1. Download the plugin\n2. Put it into your server's plugin folder\n3. Start or reload your server\n4. Enjoy the plugin!\n\n### Setup\n\n#### Maven\nTo get started with maven you first need to setup your environment to get access to the api maven package.\nTo do that simply go into your `.m2` folder which can be found at `%appData%\\..\\..\\.m2` (Open `Run` on Windows and just paste the path into there and click `Ok`).\nAfterwards if the file doesn't exist yet create the file `settings.xml` in the folder.\nThen put following stuff into the file:\n```XML\n\u003csettings xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/SETTINGS/1.0.0\n                      http://maven.apache.org/xsd/settings-1.0.0.xsd\"\u003e\n\n\t\u003cactiveProfiles\u003e\n\t\t\u003cactiveProfile\u003egithub\u003c/activeProfile\u003e\n\t\u003c/activeProfiles\u003e\n\n\t\u003cprofiles\u003e\n\t\t\u003cprofile\u003e\n\t\t\t\u003cid\u003egithub\u003c/id\u003e\n\t\t\t\u003crepositories\u003e\n\t\t\t\t\u003crepository\u003e\n\t\t\t\t\t\u003cid\u003ecentral\u003c/id\u003e\n\t\t\t\t\t\u003curl\u003ehttps://repo1.maven.org/maven2\u003c/url\u003e\n\t\t\t\t\u003c/repository\u003e\n\t\t\t\t\u003crepository\u003e\n\t\t\t\t\t\u003cid\u003egithub0\u003c/id\u003e\n\t\t\t\t\t\u003curl\u003ehttps://maven.pkg.github.com/MrNemo64/*\u003c/url\u003e\n\t\t\t\t\t\u003csnapshots\u003e\n\t\t\t\t\t\t\u003cenabled\u003etrue\u003c/enabled\u003e\n\t\t\t\t\t\u003c/snapshots\u003e\n\t\t\t\t\u003c/repository\u003e\n\t\t\t\u003c/repositories\u003e\n\t\t\u003c/profile\u003e\n\t\u003c/profiles\u003e\n\n\t\u003cservers\u003e\n\t\t\u003cserver\u003e\n\t\t\t\u003cid\u003egithub0\u003c/id\u003e\n\t\t\t\u003cusername\u003eYOUR_GITHUB_USERNAME\u003c/username\u003e\n\t\t\t\u003cpassword\u003eA_GITHUB_TOKEN\u003c/password\u003e\n\t\t\u003c/server\u003e\n\t\u003c/servers\u003e\n\u003c/settings\u003e\n```\nNow replace `YOUR_GITHUB_USERNAME` with your github username.\u003cbr\u003e\nThen go to your Github account settings and scroll down until you see `Developer settings`.\u003cbr\u003e\nGo into the `Developer settings` and then click on `Personal access tokens`.\u003cbr\u003e\nOnce you are there click on the `Generate new token` button.\u003cbr\u003e\nI would recommend you to enter `Maven packages` into the `Note` field and set the epiration to `No expiration`.\u003cbr\u003e\nThen you need to enable `repo:status` and `read:packages`. \u003cbr\u003e\nOnce you enabled those click on `Generate Token` at the bottom.\u003cbr\u003e\nNow github should show you the token, simply copy the token and replace `A_GITHUB_TOKEN` with it.\u003cbr\u003e\nThe token can be used for multiple servers so if you want to have access to another repository hosted on github simply copy the `github0` repository replace `MrNemo64` with the authors' name and copy the `github0` server. Be sure to rename the repository and server id to for example `github1` or something similar (they have to match up).\u003cbr\u003e\n\nOnce this is setup you can simply add the dependency like this in your `pom.xml`:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eme.nemo_64.betterinputs\u003c/groupId\u003e\n  \u003cartifactId\u003eapi\u003c/artifactId\u003e\n  \u003cversion\u003e0.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\nYou can get the [latest version here](https://github.com/MrNemo64/better-inputs/packages/1667483)\n\n### Usage\n\n#### Using the api to get input\n```Java\npackage me.nemo_64.betterinputs.example;\n\nimport me.nemo_64.betterinputs.api.*;\nimport me.nemo_64.betterinputs.api.input.*;\nimport me.nemo_64.betterinputs.api.input.modifier.*;\nimport me.nemo_64.betterinputs.api.platform.*;\nimport me.nemo_64.betterinputs.api.util.*;\nimport me.nemo_64.betterinputs.api.util.argument.*;\nimport me.nemo_64.betterinputs.api.util.registry.*;\nimport me.nemo_64.betterinputs.api.util.tick.*;\n\npublic final class ExampleClass {\n\n  public static void expandedExample(BetterInputs api, Object actor) {\n    // Create a input builder\n    InputBuilder\u003cString\u003e builder = api.createInput(String.class);\n    // Specify the input provider type that you want to use\n    // Depedening on what is available you might get a exception later\n    // Default types are:\n    // - betterinputs:input/chat\n    // - betterinputs:input/anvil\n    // - betterinputs:input/command_block\n    // Please note that the anvil and command_block input only work on\n    // 1.16+ as they require some packet trickery, chat however is guaranteed\n    // if BetterInputs is installed on your server\n    //\n    // We will use the anvil input type as it helps to show everything better\n    builder.type(\"betterinputs:input/anvil\");\n    // Now simply add the actor\n    // Please note that you can't just put anything in here\n    // If the actor is not available on the platform then it just won't work\n    // On bukkit everything that is a CommandSender will work though\n    builder.actor(actor);\n    // Now you can add parameters\n    // All default input types do not need any parameters but you can still provide some\n    // Check out the default input types at https://github.com/MrNemo64/better-inputs/tree/master/bukkit-parent/bukkit-core/src/main/java/me/nemo_64/betterinputs/bukkit/input\n    builder.param(\"name\", \"Our Anvil Input\");\n    builder.param(\"item\", \"Placeholder Text\");\n    // Now you can add a cancel listener\n    // This step is not required and can theoretically be ignored\n    builder.cancelListener((provider, reason) -\u003e {\n      provider.getActor().sendMessage(\"Cancelled because '\" + reason + \"'!\");\n    });\n    // Lastly we can provide a exception handler\n    // I would recommend adding the exception handler but it's not required\n    builder.execeptionHandler((throwable) -\u003e {\n      // TODO: Handle exception here\n    });\n    // Now that our builder is fully configured we can get our InputProvider\n    // Calling InputBuilder.provider() might cause some exceptions to arise if you made a mistake\n    // This includes:\n    // - Providing an invalid actor or no actor at all\n    // - Trying to get a not valid input provider type\n    InputProvider\u003cString\u003e provider = builder.provide();\n    // Now that the process is created we can do a couple other things before starting it\n    // Like adding modifiers\n    // The timeout modifier will just cancel the process once the time is up\n    // It works with ticks and therefore uses a class called TickUnit which can convert all\n    // provided time units to ticks\n    provider.withModifier(new TimeoutModifier(30, TickUnit.SECOND));\n    // There is also the attempt modifier which has to be implemented by the input provider\n    // The attempt modifier is there to validate the if a input attempt is acceptable\n    // If the X attempts (in this case 5) were not acceptable it will cancel the input process\n    // The last argument of this modifier is optional and can be removed\n    // Its only purpose is to customize the message sent to the owning actor\n    // There is a default function for it but null is not accepted\n    provider.withModifier(new AttemptModifier(5, (string) -\u003e string.endsWith(\"!\"), (actor) -\u003e actor.sendMessage(\"Please enter a valid string!\")));\n    // Lastly we can provide a modifier exception handler\n    // Basically a handler for any exception which is thrown by any of our modifiers\n    provider.withModifierExceptionHandler((modifier, exception) -\u003e {\n      // TODO: Handle modifier exception here\n    });\n    // Okay now lets start the input process\n    // The first call to this function starts it\n    // Every other call will just get the future\n    StagedFuture\u003cString\u003e future = provider.asFuture();\n    // To get the value now simply accept it like this:\n    future.thenAccept(string -\u003e {\n      // TODO: Do stuff with the value\n    });\n    // You can theoretically also transform it or work with other different things here at the end\n    // We basically used the CompletableFuture class by Java but with small improvements\n  }\n\n  public static void compactExample(BetterInputs api, Object actor) {\n    // Now lets do this in the more intended way of this api\n    // The compact \"easy\" way\n    api.createInput(String.class)\n      .actor(actor)\n      .type(\"betterinputs:input/anvil\")\n      .param(\"name\", \"Our Anvil Input\")\n      .param(\"item\", \"Placeholder Text\")\n      .cancelListener((provider, reason) -\u003e {\n        provider.getActor().sendMessage(\"Cancelled because '\" + reason + \"'!\");\n      }).exceptionHandler((throwable) -\u003e {\n        // TODO: Handle exception here\n      }).provide()\n        .withModifier(new TimeoutModifier(30, TickUnit.SECOND))\n        // I won't be using a custom message supplier here\n        .withModifier(new AttemptModifier(5, (string) -\u003e string.endsWith(\"!\")))\n        .withModifierExceptionHandler((modifier, exception) -\u003e {\n          // TODO: Handle modifier exception here\n        })\n        .asFuture().thenAccept((string) -\u003e {\n          // TODO: Do stuff with the value\n        });\n  }\n\n}\n```\n\n#### Using the api to provide input\n\nThe basics to providing input is done with two classes:\n1. The input class itself\n\n```java\npackage me.nemo_64.betterinputs.example;\n\nimport me.nemo_64.betterinputs.api.*;\nimport me.nemo_64.betterinputs.api.input.*;\nimport me.nemo_64.betterinputs.api.input.modifier.*;\nimport me.nemo_64.betterinputs.api.platform.*;\nimport me.nemo_64.betterinputs.api.util.*;\nimport me.nemo_64.betterinputs.api.util.argument.*;\nimport me.nemo_64.betterinputs.api.util.registry.*;\nimport me.nemo_64.betterinputs.api.util.tick.*;\n\npublic final class ExampleInput extends AbstractInput\u003cString\u003e {\n\n  @Override\n  protected void onStart(InputProvider\u003cString\u003e provider, IPlatformActor\u003c?\u003e actor){\n    // Here the input process is started\n    // We recommend doing your start logic here and not in the constructor\n    // As everything before here is not guaranteed to be started\n\n    // To complete the input you have to call:\n    // completeValue(V); where the value is the type of your input or null (in this case a String)\n    // or\n    // completeException(Throwable); where the value is an exception\n    \n    // If you need to access the input provider somewhere that is not in this method\n    // then you can just use AbstractInput.provider(); the method is publicly available\n    // and works if you well got an input instance so just pass the input instance around I guess\n  }\n\n  // This doesn't need to be here\n  // But it would be best to add an implementation of it\n  // So people can cancel their input process if they just don't need it anymore\n  @Override\n  protected boolean onCancel() {\n    return false; // Default is just disallowing the cancel\n  }\n\n}\n```\n\n2. The factory class which creates the input class based on the provided arguments\n\n\n```java\npackage me.nemo_64.betterinputs.example;\n\nimport me.nemo_64.betterinputs.api.*;\nimport me.nemo_64.betterinputs.api.input.*;\nimport me.nemo_64.betterinputs.api.input.modifier.*;\nimport me.nemo_64.betterinputs.api.platform.*;\nimport me.nemo_64.betterinputs.api.util.*;\nimport me.nemo_64.betterinputs.api.util.argument.*;\nimport me.nemo_64.betterinputs.api.util.registry.*;\nimport me.nemo_64.betterinputs.api.util.tick.*;\n\npublic final class ExampleInputFactory extends InputFactory\u003cString, ExampleInput\u003e {\n\n  public ExampleInputFactory(IPlatformKey key) {\n    super(key, String.class);\n    // Here in your constructor you should ready everything up that is required to work with your input.\n    // Stuff like registering listeners or similar things should be done here\n  }\n\n  // This method notifies the factory that it was unregistered\n  // A implementation is not required but if you work with for example listeners\n  // or other stuff that would be unregistered then this is the place to do it\n  @Override\n  public void onUnregister(){\n\n  }\n\n  // Here your input is created\n  // You are provided all arguments that the other plugin using your input provided you with\n  // As well as the actor that is owning the input process\n  @Override\n  protected ExampleInput provide(IPlatformActor\u003c?\u003e actor, ArgumentMap map){\n    return new ExampleInput();\n  }\n\n}\n```\n\nTo register everything you need a platform identifiable object.\nFor bukkit a platform identifiable object is a plugin.\nSo here a sample plugin class that provides input:\n\n```java \npackage me.nemo_64.betterinputs.example;\n\nimport me.nemo_64.betterinputs.api.*;\nimport me.nemo_64.betterinputs.api.input.*;\nimport me.nemo_64.betterinputs.api.input.modifier.*;\nimport me.nemo_64.betterinputs.api.platform.*;\nimport me.nemo_64.betterinputs.api.util.*;\nimport me.nemo_64.betterinputs.api.util.argument.*;\nimport me.nemo_64.betterinputs.api.util.registry.*;\nimport me.nemo_64.betterinputs.api.util.tick.*;\n\npublic final class ExamplePlugin extends JavaPlugin {\n\n  @Override\n  public void onEnable() {\n    // We recommend using this approach for getting the api\n    BetterInputs\u003c?\u003e api = Bukkit.getServicesManager().getRegistration(BetterInputs.class).getProvider();\n    // Theoretically you could also use:\n    // BetterInputs\u003c?\u003e api = BetterInputs.getPlatform();\n    IPlatformKeyProvider keyProvider = api.tryGetKeyProvider(this).get();\n    // The key can be anything, really\n    api.registerInputFactory(new ExampleInputFactory(keyProvider.getKey(\"input/example\")));\n  }\n\n}\n```\n\nAnd about the plugin.yml\n```yml\nmain: me.nemo_64.betterinputs.example.ExamplePlugin\nname: BetterInputsExample\nauthors: [MrNemo64, Lauriichan]\nversion: 0.1.0\napi-version: 1.13\ndepend: [BetterInputs]\n```\n\n\u003c!-- ROADMAP --\u003e\n## Roadmap\n\nSee the [open issues](https://github.com/MrNemo64/better-inputs/issues) for a list of proposed features (and known issues).\n\n\n\n\u003c!-- CONTRIBUTING --\u003e\n## Contributing\n\nContributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n\n\n\u003c!-- LICENSE --\u003e\n## License\n\nDistributed under the MIT License. See `LICENSE` for more information.\n\n\n\n\u003c!-- CONTACT --\u003e\n## Contact\n\nProject Link: [https://github.com/MrNemo64/better-inputs](https://github.com/MrNemo64/better-inputs)\n\n\n\n\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES --\u003e\n\u003c!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --\u003e\n[contributors-shield]: https://img.shields.io/github/contributors/MrNemo64/better-inputs.svg?style=flat-square\n[contributors-url]: https://github.com/MrNemo64/better-inputs/graphs/contributors\n[stars-shield]: https://img.shields.io/github/stars/MrNemo64/better-inputs.svg?style=flat-square\n[stars-url]: https://github.com/MrNemo64/better-inputs/stargazers\n[issues-shield]: https://img.shields.io/github/issues/MrNemo64/better-inputs.svg?style=flat-square\n[issues-url]: https://github.com/MrNemo64/better-inputs/issues\n[license-shield]: https://img.shields.io/github/license/MrNemo64/better-inputs.svg?style=flat-square\n[license-url]: https://github.com/MrNemo64/better-inputs/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrnemo64%2Fbetter-inputs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrnemo64%2Fbetter-inputs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrnemo64%2Fbetter-inputs/lists"}