Skip to content

Commit ce0c218

Browse files
authored
Merge pull request #12 from integr-dev/develop
This pull request introduces several new features and improvements to the Backbone scripting system, focusing on enhancing script lifecycle management, HTTP request handling, and JSON construction. It also refactors event handling for inter-script communication and simplifies command, item, and entity registration. The documentation (README.md) has been updated to reflect these changes and provide new usage examples. Key changes include: 1. HTTP Request Utilities and Documentation Added new utility functions (request, requestSync, and requestAndThen) for making HTTP requests from scripts, including both synchronous and asynchronous variants. These utilities are now documented in the README.md with usage examples. 2. Script Lifecycle and Registration DSL Improvements Extracted the LifecycleBuilder and lifecycle DSL entrypoint into a dedicated file, improving modularity and clarity. Added new DSL functions: useCommand, useItem, and useEntity for simplified registration and unregistration of commands, items, and entities in script lifecycles. Updated the documentation to demonstrate the new registration DSL and improved lifecycle examples. 3. Inter-Script Communication Refactor Renamed InterScriptDuckTypedEvent to IscEvent and moved it to a new package for clarity and consistency. Updated all usages accordingly. Renamed the DSL function from interScript to interScriptListener to better reflect its purpose and updated the documentation. 4. JSON Builder Utility Introduced a new JsonBuilder utility and DSL for constructing JSON objects and arrays in scripts, along with helper functions jsonTree and json. 5. Minor Documentation and Logging Updates Improved logging in lifecycle hooks for better debugging. Minor documentation and formatting updates in README.md, including placeholder section cleanup. These changes collectively make scripting with Backbone more powerful, modular, and user-friendly.
2 parents f92aa4f + 18b90b3 commit ce0c218

15 files changed

Lines changed: 1108 additions & 124 deletions

File tree

README.md

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ lifecycle {
9090
var otherCounter = 0
9191

9292
onLoad {
93-
Backbone.registerListener(this)
93+
println("Script loaded! Counter: $counter | Other Counter: $otherCounter")
9494
}
9595

9696
onUnload {
97-
Backbone.unregisterListener(this)
97+
println("Script unloaded! Counter: $counter | Other Counter: $otherCounter")
9898
}
9999

100100
// This event fires every server tick while the script is enabled.
@@ -279,7 +279,7 @@ Use `interScript` to listen for messages with a specific id. The handler receive
279279

280280
```kotlin
281281
lifecycle {
282-
interScript("abc") { map ->
282+
interScriptListener("abc") { map ->
283283
val abc = map.pull<String>("abc")
284284
println("Received inter-script message: $abc")
285285
}
@@ -291,6 +291,34 @@ lifecycle {
291291
- The data is passed as an immutable `IscMap`, which supports type-safe retrieval with `pull<T>(key)`.
292292
- This system is ideal for modular scripts, cross-script events, and decoupled communication.
293293

294+
### HTTP Requests in Scripts
295+
296+
Backbone scripts can easily make HTTP requests and handle responses using the built-in DSL. This is useful for integrating with web APIs, fetching data, or interacting with external services directly from your scripts.
297+
298+
#### Example: Making an HTTP Request in a Script
299+
300+
You can use the `requestAndThen` function inside your script's lifecycle to perform HTTP requests asynchronously. The response is provided to a callback, where you can process the result and interact with the server.
301+
302+
```kotlin
303+
lifecycle {
304+
onLoad {
305+
requestAndThen("https://httpbin.org/get", HttpMethod.GET, {
306+
header("User-Agent", "Backbone Script Handler")
307+
}) { response ->
308+
Backbone.SERVER.broadcast(component {
309+
append("HTTP Response: ${response.json()}") {
310+
color(Color.GREEN)
311+
}
312+
})
313+
}
314+
}
315+
}
316+
```
317+
318+
- `requestAndThen(url, method, { ...headers... }) { response -> ... }` performs an HTTP request and provides the response to the callback.
319+
- The `response` object supports JSON parsing and mapping, making it easy to work with API responses.
320+
- You can use this in any lifecycle hook, such as `onLoad`, or in event listeners.
321+
294322
### Commands
295323

296324
Backbone's command framework makes it easy to create and manage commands with arguments, subcommands, and permission checks.
@@ -331,14 +359,9 @@ object MyCommand : Command("mycommand", "My first command") {
331359
}
332360
}
333361

334-
// In your ManagedLifecycle's onLoad:
362+
// In your ManagedLifecycle:
335363
lifecycle {
336-
onLoad {
337-
Backbone.Handler.COMMAND.register(MyCommand)
338-
}
339-
onUnload {
340-
Backbone.Handler.COMMAND.unregister(MyCommand)
341-
}
364+
useCommand(MyCommand)
342365
}
343366
```
344367

@@ -396,11 +419,9 @@ object MyItemState : CustomItemState(Material.DIAMOND_SWORD, "default") {
396419
}
397420
}
398421

399-
// In your ManagedLifecycle's onLoad:
422+
// In your ManagedLifecycle:
400423
lifecycle {
401-
onLoad {
402-
Backbone.Handler.ITEM.register(MyItem)
403-
}
424+
useItem(MyItem)
404425
}
405426
```
406427

@@ -429,11 +450,9 @@ object GuardEntity : CustomEntity<Zombie>("guard", EntityType.ZOMBIE) {
429450
}
430451
}
431452

432-
// In your ManagedLifecycle's onLoad:
453+
// In your ManagedLifecycle:
433454
lifecycle {
434-
onLoad {
435-
Backbone.Handler.ENTITY.register(GuardEntity)
436-
}
455+
useEntity(GuardEntity)
437456
}
438457

439458
// You can then spawn the entity, for example, using a command
@@ -581,5 +600,4 @@ Backbone provides a set of placeholders through its soft dependency on Placehold
581600

582601
- `%backbone_version%`: Displays the current version of the Backbone plugin.
583602

584-
More placeholders are planned for future releases.
585-
603+
More placeholders are planned for future releases.

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
}
88

99
group = "net.integr"
10-
version = "1.6.1"
10+
version = "1.7.0"
1111

1212
repositories {
1313
mavenCentral()

src/main/kotlin/net/integr/backbone/systems/hotloader/isc/InterScriptDuckTypedEvent.kt renamed to src/main/kotlin/net/integr/backbone/events/IscEvent.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@
1111
* limitations under the License.
1212
*/
1313

14-
package net.integr.backbone.systems.hotloader.isc
14+
package net.integr.backbone.events
1515

1616
import net.integr.backbone.systems.event.Event
17+
import net.integr.backbone.systems.hotloader.isc.IscMap
1718

1819
/**
1920
* Event for inter-script communication, carrying a message id and data.
2021
*
2122
* Used internally by the lifecycle DSL for inter-script messaging.
2223
* @property id The message id.
23-
* @property data The message data as [IscMap].
24+
* @property data The message data as [net.integr.backbone.systems.hotloader.isc.IscMap].
2425
* @since 1.6.0
2526
*/
26-
class InterScriptDuckTypedEvent(val id: String, val data: IscMap) : Event()
27+
class IscEvent(val id: String, val data: IscMap) : Event()

src/main/kotlin/net/integr/backbone/systems/hotloader/GlobalScriptFunctions.kt

Lines changed: 115 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -14,114 +14,141 @@
1414
package net.integr.backbone.systems.hotloader
1515

1616
import net.integr.backbone.Backbone
17-
import net.integr.backbone.systems.event.BackboneEventHandler
18-
import net.integr.backbone.systems.hotloader.isc.InterScriptDuckTypedEvent
17+
import net.integr.backbone.events.IscEvent
18+
import net.integr.backbone.systems.command.Command
19+
import net.integr.backbone.systems.entity.CustomEntity
1920
import net.integr.backbone.systems.hotloader.isc.IscMap
2021
import net.integr.backbone.systems.hotloader.isc.IscMapBuilder
21-
import net.integr.backbone.systems.hotloader.lifecycle.LifecycleSustainedState
22-
import net.integr.backbone.systems.hotloader.lifecycle.ManagedLifecycle
23-
import net.integr.backbone.systems.hotloader.lifecycle.sustained
24-
import net.integr.backbone.systems.text.component
25-
import java.awt.Color
26-
import kotlin.inc
22+
import net.integr.backbone.systems.item.CustomItem
23+
import net.integr.backbone.systems.network.http.HttpMethod
24+
import net.integr.backbone.systems.network.http.Requestor
25+
import net.integr.backbone.systems.network.http.request.RequestBuilder
26+
import net.integr.backbone.systems.network.http.response.Response
27+
import org.bukkit.entity.Mob
2728
import kotlin.reflect.full.starProjectedType
28-
import kotlin.toString
2929

3030
/**
31-
* DSL entrypoint for defining a script lifecycle.
31+
* Makes an asynchronous HTTP request to the given URI with the specified method and request builder block.
3232
*
33-
* @param block The lifecycle configuration block.
34-
* @return The constructed [ManagedLifecycle].
33+
* @param uri The target URI for the HTTP request.
34+
* @param method The HTTP method to use (e.g., GET, POST).
35+
* @param builderBlock An optional block to configure the request using a [RequestBuilder].
36+
* @return A [Response] containing the response data as a string.
3537
* @since 1.6.0
3638
*/
37-
fun lifecycle(block: LifecycleBuilder.() -> Unit): ManagedLifecycle {
38-
val builder = LifecycleBuilder()
39-
block(builder)
40-
return builder
41-
}
39+
suspend fun request(uri: String, method: HttpMethod, builderBlock: RequestBuilder.() -> Unit = {}) =
40+
Requestor.request(uri, method, builderBlock)
4241

4342
/**
44-
* Builder for script lifecycle and event/listener registration DSL.
43+
* Makes a synchronous HTTP request to the given URI with the specified method and request builder block.
4544
*
46-
* Provides methods for registering load/unload hooks, event listeners, and inter-script communication handlers.
45+
* @param uri The target URI for the HTTP request.
46+
* @param method The HTTP method to use (e.g., GET, POST).
47+
* @param builderBlock An optional block to configure the request using a [RequestBuilder].
48+
* @return A [Response] containing the response data as a string.
4749
* @since 1.6.0
4850
*/
49-
class LifecycleBuilder : ManagedLifecycle() {
50-
val onLoadCalls: MutableList<() -> Unit> = mutableListOf()
51-
val onUnloadCalls: MutableList<() -> Unit> = mutableListOf()
51+
fun requestSync(uri: String, method: HttpMethod, builderBlock: RequestBuilder.() -> Unit = {}) =
52+
Requestor.requestSync(uri, method, builderBlock)
5253

53-
override fun onLoad() {
54-
onLoadCalls.forEach { it() }
55-
}
54+
/**
55+
* Makes an asynchronous HTTP request to the given URI with the specified method and request builder block, then executes a callback with the response.
56+
*
57+
* @param uri The target URI for the HTTP request.
58+
* @param method The HTTP method to use (e.g., GET, POST).
59+
* @param builderBlock An optional block to configure the request using a [RequestBuilder].
60+
* @param then A callback block that receives the [Response] containing the response data as a string.
61+
* @since 1.6.0
62+
*/
63+
fun requestAndThen(uri: String, method: HttpMethod, builderBlock: RequestBuilder.() -> Unit = {}, then: (Response<String>) -> Unit)
64+
= Requestor.requestAndThen(uri, method, builderBlock, then)
5665

57-
override fun onUnload() {
58-
onUnloadCalls.forEach { it() }
59-
}
66+
/**
67+
* Registers a Bukkit event listener for the given event type.
68+
*
69+
* @param priority The Bukkit event priority (default: NORMAL).
70+
* @param block The event handler block.
71+
* @since 1.6.0
72+
*/
73+
inline fun <reified T : org.bukkit.event.Event> LifecycleBuilder.listener(
74+
priority: org.bukkit.event.EventPriority = org.bukkit.event.EventPriority.NORMAL,
75+
noinline block: (T) -> Unit
76+
) {
77+
onLoad { Backbone.SERVER.pluginManager.registerEvent(T::class.java, this, priority, { _, event -> if (event is T) block(event) }, Backbone.PLUGIN) }
78+
onUnload { Backbone.unregisterListener(this) }
79+
}
6080

61-
/**
62-
* Registers a block to run when the script is loaded.
63-
* @since 1.6.0
64-
*/
65-
fun onLoad(block: () -> Unit) {
66-
onLoadCalls += block
67-
}
81+
/**
82+
* Registers a Backbone event listener for the given event type.
83+
*
84+
* @param priority The Backbone event priority (default: NORMAL).
85+
* @param block The event handler block.
86+
* @since 1.6.0
87+
*/
88+
inline fun <reified T : net.integr.backbone.systems.event.Event> LifecycleBuilder.backboneListener(
89+
priority: net.integr.backbone.systems.event.EventPriority = net.integr.backbone.systems.event.EventPriority.NORMAL,
90+
noinline block: (T) -> Unit
91+
) {
92+
onLoad { Backbone.EVENT_BUS.registerLambda(T::class.starProjectedType, priority, this) { event -> if (event is T) block(event) } }
93+
onUnload { Backbone.unregisterListener(this) }
94+
}
6895

69-
/**
70-
* Registers a block to run when the script is unloaded.
71-
* @since 1.6.0
72-
*/
73-
fun onUnload(block: () -> Unit) {
74-
onUnloadCalls += block
96+
/**
97+
* Registers a handler for inter-script communication events with the given id.
98+
*
99+
* @param id The message id to listen for.
100+
* @param block The handler block, receiving the message data as [IscMap].
101+
* @since 1.6.0
102+
*/
103+
fun LifecycleBuilder.interScriptListener(id: String, block: (IscMap) -> Unit) {
104+
backboneListener<IscEvent> {
105+
if (it.id == id) block(it.data)
75106
}
107+
}
76108

77-
/**
78-
* Registers a Bukkit event listener for the given event type.
79-
*
80-
* @param priority The Bukkit event priority (default: NORMAL).
81-
* @param block The event handler block.
82-
* @since 1.6.0
83-
*/
84-
inline fun <reified T : org.bukkit.event.Event> listener(priority: org.bukkit.event.EventPriority = org.bukkit.event.EventPriority.NORMAL, crossinline block: (T) -> Unit) {
85-
onLoadCalls += { Backbone.SERVER.pluginManager.registerEvent(T::class.java, this, priority, { _, event -> if (event is T) block(event) }, Backbone.PLUGIN) }
86-
onUnloadCalls += { Backbone.unregisterListener(this) }
87-
}
109+
/**
110+
* Dispatches an inter-script communication event with the given id and data.
111+
*
112+
* @param id The message id to send.
113+
* @param data The data builder block for the message.
114+
* @since 1.6.0
115+
*/
116+
fun dispatchInterScript(id: String, data: IscMapBuilder.() -> Unit) {
117+
val builder = IscMapBuilder()
118+
builder.data()
119+
val isc = builder.build()
120+
Backbone.EVENT_BUS.post(IscEvent(id, isc))
121+
}
88122

89-
/**
90-
* Registers a Backbone event listener for the given event type.
91-
*
92-
* @param priority The Backbone event priority (default: NORMAL).
93-
* @param block The event handler block.
94-
* @since 1.6.0
95-
*/
96-
inline fun <reified T : net.integr.backbone.systems.event.Event> backboneListener(priority: net.integr.backbone.systems.event.EventPriority = net.integr.backbone.systems.event.EventPriority.NORMAL, noinline block: (T) -> Unit) {
97-
onLoadCalls += { Backbone.EVENT_BUS.registerLambda(T::class.starProjectedType, priority, this) { event -> if (event is T) block(event) } }
98-
onUnloadCalls += { Backbone.unregisterListener(this) }
99-
}
123+
/**
124+
* Registers a command handler for the given command.
125+
*
126+
* @param command The command to register.
127+
* @since 1.6.0
128+
*/
129+
fun LifecycleBuilder.useCommand(command: Command) {
130+
onLoad { Backbone.Handler.COMMAND.register(command) }
131+
onUnload { Backbone.Handler.COMMAND.unregister(command) }
132+
}
100133

101-
/**
102-
* Registers a handler for inter-script communication events with the given id.
103-
*
104-
* @param id The message id to listen for.
105-
* @param block The handler block, receiving the message data as [IscMap].
106-
* @since 1.6.0
107-
*/
108-
fun interScript(id: String, block: (IscMap) -> Unit) {
109-
backboneListener<InterScriptDuckTypedEvent> {
110-
if (it.id == id) block(it.data)
111-
}
112-
}
134+
/**
135+
* Registers an entity handler for the given custom entity.
136+
*
137+
* @param entity The custom entity to register.
138+
* @since 1.6.0
139+
*/
140+
fun <T : Mob> LifecycleBuilder.useEntity(entity: CustomEntity<T>) {
141+
onLoad { Backbone.Handler.ENTITY.register(entity) }
142+
onUnload { Backbone.Handler.ENTITY.unregister(entity) }
143+
}
113144

114-
/**
115-
* Dispatches an inter-script communication event with the given id and data.
116-
*
117-
* @param id The message id to send.
118-
* @param data The data builder block for the message.
119-
* @since 1.6.0
120-
*/
121-
fun dispatchInterScript(id: String, data: IscMapBuilder.() -> Unit) {
122-
val builder = IscMapBuilder()
123-
builder.data()
124-
val isc = builder.build()
125-
Backbone.EVENT_BUS.post(InterScriptDuckTypedEvent(id, isc))
126-
}
145+
/**
146+
* Registers an item handler for the given custom item.
147+
*
148+
* @param item The custom item to register.
149+
* @since 1.6.0
150+
*/
151+
fun LifecycleBuilder.useItem(item: CustomItem) {
152+
onLoad { Backbone.Handler.ITEM.register(item) }
153+
onUnload { Backbone.Handler.ITEM.unregister(item) }
127154
}

0 commit comments

Comments
 (0)