{"id":15281428,"url":"https://github.com/jakobkmar/kspigot","last_synced_at":"2025-12-28T17:58:54.015Z","repository":{"id":37010055,"uuid":"275054909","full_name":"jakobkmar/KSpigot","owner":"jakobkmar","description":"Extended Spigot and Bukkit API for Kotlin","archived":false,"fork":false,"pushed_at":"2024-08-09T20:51:18.000Z","size":5848,"stargazers_count":142,"open_issues_count":1,"forks_count":33,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-06T22:08:41.304Z","etag":null,"topics":["api","bukkit","gui","kotlin","kotlin-spigot","kotlin-wrapper","kspigot","spigot","spigot-extension"],"latest_commit_sha":null,"homepage":"https://jakobkmar.github.io/KSpigot","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jakobkmar.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2020-06-26T02:10:56.000Z","updated_at":"2025-02-25T21:03:35.000Z","dependencies_parsed_at":"2024-02-03T15:29:35.314Z","dependency_job_id":"877907ad-26e2-47b3-83b3-7f155452fcd5","html_url":"https://github.com/jakobkmar/KSpigot","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobkmar%2FKSpigot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobkmar%2FKSpigot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobkmar%2FKSpigot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakobkmar%2FKSpigot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jakobkmar","download_url":"https://codeload.github.com/jakobkmar/KSpigot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247557767,"owners_count":20958047,"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":["api","bukkit","gui","kotlin","kotlin-spigot","kotlin-wrapper","kspigot","spigot","spigot-extension"],"created_at":"2024-09-30T13:07:51.230Z","updated_at":"2025-10-14T07:11:25.575Z","avatar_url":"https://github.com/jakobkmar.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KSpigot\n\n[ ![Latest version](https://img.shields.io/maven-central/v/net.axay/kspigot?color=pink\u0026label=latest%20version\u0026style=for-the-badge) ](https://repo1.maven.org/maven2/net/axay/kspigot/)\n[ ![Guide](https://img.shields.io/badge/guide-read-%23c2ff73?style=for-the-badge) ](https://jakobkmar.github.io/KSpigot/)\n[ ![Discord](https://img.shields.io/discord/771140534118383626?color=cyan\u0026label=DISCORD\u0026style=for-the-badge) ](https://discord.gg/CJDUVuJ) \u003cbr\u003e\n\nKSpigot is a Kotlin library for the popular [spigot server software](https://spigotmc.org/) for minecraft. It adds\nlots of useful features, builders and extensions for the Spigot API itself - but KSpigot also brings new things like an\nInventory GUI API, or Brigardier support.\n\n## Dependency\n\nKSpigot is available on Maven Central.\n\nGradle:\n\n```kt\nimplementation(\"net.axay:kspigot:$kspigotVersion\")\n```\n\nRead the [setup guide](https://jakobkmar.github.io/KSpigot/setup/gradle) to get started!\n\n## Guide\n\nYou will find the best information about KSpigot in the [guide](https://jakobkmar.github.io/KSpigot/).\n\n## Contact\n\nJoin our Discord Server (click on the badge above)\n\n## Old tutorials\n\nThe following content consist of some features which haven't already been migrated to the new\n[guide](https://jakobkmar.github.io/KSpigot/).\n\n### Chainable runnables\n\nThis makes it possible to do resource intensive tasks asynchronous and then doing something with the result\nsynchronous (e.g. because Spigot forces you) in a simple way.\n\n```kotlin\nfirstAsync {\n    // do a resource intensive task\n    ArrayList\u003cBlock\u003e() // -\u003e this will be forwarded to the next part of the chain as \"it\"\n}.thenSync {\n    // do something with the result\n    it.forEach { }\n}.thenAsync {\n    // and so on...\n}.execute()\n```\n\n### Inventory GUI API\n\nInventories are great for viewing GUI information. However, they are not designed for developing GUIs. The KSpigot\nInventory GUI API provides an easy way to build inventory GUIs the way you would expect such an API to be. In addition,\nit offers full type safety for slots. Attention, the Slots is designed from bottom to top, so the Slots.RowOneSlotOne is the slot at bottom left.\n\n```kotlin\nval gui = kSpigotGUI(GUIType.FIVE_BY_NINE) {\n    title = literalText(\"Example Inventory\")\n\n    page(1) {\n        // slot ranges like rectTo or linTo reduce the amount of code\n        placeholder(Slots.RowOneSlotOne rectTo Slots.RowFiveSlotNine, ItemStack(Material.RED_STAINED_GLASS))\n        nextPage(Slots.RowOneSlotNine, ItemStack(Material.PAPER))\n    }\n\n    page(2) {\n        // define fancy transitions\n        transitionFrom = PageChangeEffect.SLIDE_HORIZONTALLY\n        transitionTo = PageChangeEffect.SLIDE_HORIZONTALLY\n\n        // get special slot compounds easily with constants like Slots.Border\n        placeholder(Slots.Border, ItemStack(Material.GLASS_PANE))\n        \n        // page change buttons\n        previousPage(Slots.RowTwoSlotTwo, ItemStack(Material.PAPER))\n        nextPage(Slots.RowTwoSlotEight, ItemStack(Material.PAPER))\n\n        // a button with a custom callback\n        button(Slots.RowThreeSlotFive, ItemStack(Material.REPEATER)) {\n            // change content of the current view\n            it.guiInstance[Slots.RowTwoSlotFive] = ItemStack(Material.values().random(), (1..64).random())\n        }\n\n        // a slot where player interaction is permitted\n        freeSlot(Slots.RowTwoSlotFive)\n    }\n\n    page(3) {\n        // placeholders are there to block any player action while displaying a specific item\n        placeholder(Slots.RowOneSlotOne rectTo Slots.RowFiveSlotNine, ItemStack(Material.PINK_GLAZED_TERRACOTTA))\n\n        // change to a specific page\n        pageChanger(Slots.RowThreeSlotFive, ItemStack(Material.DIAMOND), 1)\n    }\n}\n```\n\nThis example: _This inventory has three pages. On page 1, there is a button for generating random ItemStacks. The player\ncan take out this ItemStack and move it to his own inventory._\n\nThen you can open the GUI for any player.\n\n```kotlin\nplayer.openGUI(gui)\n```\n\n### Complex chat components\n\n**DEPRECATED** Use `literalText` instead. More info will be available in the guide soon.\n\nCreating chat components can get very messy quickly. However, creating a component with KSpigot is much more\ndeveloper-friendly.\n\n```kotlin\nval component = chatComponent {\n    text(\"You got a friend request! \") {\n        color = col(\"#4FEA40\")\n        isBold = true\n    }\n\n    text(\"[Accept]\") {\n        color = ChatColor.WHITE\n        clickEvent(ClickEvent.Action.RUN_COMMAND, \"friend accept Foo\")\n        hoverEventText {\n            text(\"Click here to accept the friend request!\") { color = ChatColor.RED }\n        }\n    }\n}\n```\n\nYou can also access the builder and immediately send the message.\n\n```kotlin\ncommandSender.sendMessage { /* same in here as above */ }\n```\n\n### Firework API\n\nTutorial still missing, both here and in the guide\n\n### NBTData support\n\nTypesafe and consistent\n\n```kotlin\n// load nbt\nval nbt = entity.nbtData\n\n// retrieve data via keys\nval health = nbt[\"hearts\", NBTDataType.INT]\n\n// set data for a given key\nnbt[\"custom\", NBTDataType.DOUBLE] = 3.3\n\n// delete data for a given key\nnbt -= \"keyToDelete\"\n\n// save data to the entity\nentity.nbtData = nbt\n\n// serialization support\nval serializedString = nbt.serialize()\nval deserializeMethod1 = NBTData(serializedString)\nval deserializeMethod2 = NBTData.deserialize(serializedString)\n```\n\n### Simple extension functions and values\n\n```kotlin\nlivingEntity.isInWater // checks if both feet and head are in water\nlivingEntity.isHeadInWater // checks if the head (eye location) is in water\nentity.isFeetInWater // checks if the feet are in water\nentity.isGroundSolid // checks if the entity stands on solid material\ndamageable.kill() // instantly kills the damageable\nlivingEntity.heal() // sets the health to the maximum health (if given - else throws Exception)\nplayer.feed() // sets the players food level to 20\nplayer.saturate() // sets the players saturation level to the current max value\nplayer.feedSaturate() // sets the players food and saturation level to 20\nplayer.disappear(plugin) // all other players won't be able to see the player anymore\nplayer.appear(plugin) // show the player to every other player\nvector.isFinite // checks if x, y and z of the vector are all finite\nplayerInteractEntityEvent.interactItem // gets the item the player interacted with\nprepareItemCraftEvent.isCancelled // checks if the event isCancelled\nprepareItemCraftEvent.cancel() // cancels the PrepareItemCraftEvent\n```\n\n### Direction API\n\nHandles the hassle of struggling with direction angles for you.\n\n```kotlin\nval cardinal = CardinalDirection.fromLocation(loc) // NORTH, EAST, SOUTH, WEST\nval vertical = VerticalDirection.fromLocation(loc) // UP, DOWN, STRAIGHT\n\n// convert to BlockFace\nval blockFace = cardinal.facing\n```\n\n### CustomItemIdentifiers\n\nYou want to mess with resourcepacks and extend your possibilities? \u003cbr\u003e\nSpigot is lacking a representation of custom items (via custom model data). This is what the data\nclass `CustomItemIdentifier` is for.\n\n```kotlin\nval identifier = CustomItemIdentifier(itemStack)\n// or\nval identifier = CustomItemIdentifier(1001, Material.IRON_NUGGET)\n\n// get an itemstack with the custom model data applied\nval stack = identifier.itemStack\n```\n\n### Flexible and chainable geometry syntax\n\nMakes complex modification of locations and vectors more intuitive. Also, you can use any type of number (`Short`, `Int`\n, `Long`, `Float`, `Double`) you want. You do not have to mess with different data types.\n\n```kotlin\nloc increaseX 3 reduce vec(3.0, 1.5f, 3) increaseYZ 5.7\nloc + vecXY(3, 7f) - vecZ(3)\nloc - vec(x = 3, z = 5.6f) * 3 * vecXZ(7, 3.1)\n```\n\n### Structures\n\nA structure is a set of data defining what is inside a specific area.\n\n#### LocationArea\n\nA LocationArea is an area between to given Locations. The max and min locations will be calculated automatically.\n\n```kotlin\nval area = LocationArea(loc1, loc2) // loc1 and loc2 do not have to be min and max\narea.minLoc\narea.maxLoc\narea.touchedChunks // get all chunks the LocationArea \"lays\" in\narea.isInArea(loc3, check3d = true, tolerance = 0)\n\narea.fillBlocks.forEach { /* execute task for each block in the area*/ }\narea.entities.forEach { /* execute task for each entity in the area*/ }\n```\n\n#### Loading a structure\n\nA structure can be loaded from any given LocationArea:\n\n```kotlin\nval structure = area.loadStructure(includeBlocks = true, includeEntities = false)\n```\n\n#### Using a structure\n\nStructures can be transformed and placed in the world.\n\n```kotlin\n// rotate the structure (angle in degrees)\nstructure.rotateAroundX(angle)\nstructure.rotateAroundY(angle)\nstructure.rotateAroundZ(angle)\n\n// place the structure at the given location\nstructure.buildAt(loc)\n```\n\n#### Default structures\n\n##### Circle\n\nThere are different circle types, all inheriting from `Circle`.\n\n```kotlin\nval circle = MaterialCircle(radius, Material.GRASS_BLOCK)\nval circle = ParticleCircle(radius, particle(Particle.HEART) { amount = 5 })\nval circle = EntityCircle(radius, EntityType.COW)\n```\n\nA circle can be filled, or it can only consist of its border (edge).\n\n```kotlin\n// get all circle locations\ncircle.fillLocations\ncircle.edgeLocations\n\n// get a structure from the circle\ncircle.filledStructure\ncircle.edgeStructure\n```\n\n### IP Address API\n\nThis API allows you to easily get some data from the IP address of a player. Please note that it is not promised that\nthis always returns data: _After exceeding a certain amount of request per minute, the request will return null._\n\n```kotlin\nplayer.ipAddressData\n// or (for results in another language)\nplayer.ipAddressData(IPAddressDataLanguage.GERMAN)\n```\n\nWhat kind of data is available?\n\n```kotlin\nipData ?: return\n\nipData.district\nipData.city\nipData.continent\nipData.country\n// and more...\n```\n\n### Particles\n\nThis part of the API makes it more intuitive to deal with particles.\n\n```kotlin\n// define the particle\nval particle = particle(Particle.BLOCK_CRACK) {\n    amount = 10\n    offset = vec(3, 3, 3)\n    extra = 0.1\n    force = true\n}\n\n// spawn the particle\nparticle.spawnAt(loc)\nparticle.spawnFor(player)\n```\n\nYou can also access the builder as follows (and instantly spawn the particle).\n\n```kotlin\nloc.particle(Particle.HEART) { }\nplayer.particle(Particle.HEART) { }\n```\n\n### GamePhase API\n\nGame phases are commonly used with minigames. This is why KSpigot provides a general way to create such a game phase\nsystem quickly.\n\n```kotlin\nval game = buildGame {\n    phase(length) {\n        counterMessage(\"The game will start in\", \"seconds\", \"second\", \"\u003e\u003e\", \".\")\n\n        end {\n            broadcast(\"The game has started.\")\n        }\n    }\n\n    phase(length) {\n        // alternative counterMessage implementation\n        counterMessage {\n            \"\u003e\u003e The special event will start in $it seconds.\"\n        }\n\n        start { /* do something in the beginning of the gamephase */ }\n        end { /* e.g. start the event */ }\n    }\n}\n\ngame.begin()\n```\n\nIdle phases are still in development.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakobkmar%2Fkspigot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjakobkmar%2Fkspigot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakobkmar%2Fkspigot/lists"}