first commit

This commit is contained in:
Alexander Medvedev 2026-04-15 20:08:21 +02:00
commit 56da082f55
10 changed files with 7179 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "wit/repo"]
path = wit/repo
url = https://github.com/Pumpkin-MC/Pumpkin.git

13
CMakeLists.txt Normal file
View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.10)
project(pumpkin-api-c C)
set(CMAKE_C_STANDARD 11)
# Add the generated bindings
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/gen)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(pumpkin-api STATIC
src/gen/plugin.c
src/pumpkin_api.c
)

55
README.md Normal file
View File

@ -0,0 +1,55 @@
# Pumpkin Plugin API for C
This package provides everything needed to write a Pumpkin server plugin compiled to WebAssembly using C or C++.
## Quick start
1. Clone this repository with submodules:
```bash
git clone --recursive <url-to-this-repo>
# Or if you already cloned it:
git submodule update --init --recursive
```
2. Create your plugin (`main.c`):
```c
#include "pumpkin_api.h"
#include <stdio.h>
pumpkin_metadata_t get_meta(void) {
static const char* authors[] = {"you"};
return (pumpkin_metadata_t) {
.name = "my-c-plugin",
.version = "0.1.0",
.authors = authors,
.authors_count = 1,
.description = "A simple C plugin for Pumpkin",
.dependencies_count = 0
};
}
void on_load(plugin_own_context_t ctx) {
printf("C plugin loaded!\n");
}
REGISTER_PUMPKIN_PLUGIN(((pumpkin_plugin_t){
.get_metadata = get_meta,
.on_load = on_load
}))
```
3. Build your plugin into a WebAssembly component:
To build for Pumpkin, you'll need the `wasi-sdk` and `wit-bindgen`.
```bash
# Compile to Wasm using wasi-sdk
/path/to/wasi-sdk/bin/clang -O3 \
-Iinclude -Isrc/gen \
src/gen/plugin.c src/pumpkin_api.c example/main.c \
-o my_plugin.wasm \
-mexec-model=reactor
```

28
example/main.c Normal file
View File

@ -0,0 +1,28 @@
#include "pumpkin_api.h"
#include <stdio.h>
pumpkin_metadata_t get_meta(void) {
static const char* authors[] = {"alex"};
return (pumpkin_metadata_t) {
.name = "my-c-plugin",
.version = "0.1.0",
.authors = authors,
.authors_count = 1,
.description = "A simple C plugin for Pumpkin",
.dependencies_count = 0
};
}
void on_load(plugin_own_context_t ctx) {
printf("C plugin loaded!\n");
}
void on_unload(plugin_own_context_t ctx) {
printf("C plugin unloaded!\n");
}
REGISTER_PUMPKIN_PLUGIN(((pumpkin_plugin_t){
.get_metadata = get_meta,
.on_load = on_load,
.on_unload = on_unload
}))

41
include/pumpkin_api.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef PUMPKIN_API_H
#define PUMPKIN_API_H
#include "plugin.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
const char* name;
const char* version;
const char** authors;
size_t authors_count;
const char* description;
const char** dependencies;
size_t dependencies_count;
} pumpkin_metadata_t;
typedef void (*pumpkin_on_load_t)(plugin_own_context_t ctx);
typedef void (*pumpkin_on_unload_t)(plugin_own_context_t ctx);
typedef pumpkin_metadata_t (*pumpkin_get_metadata_t)(void);
typedef struct {
pumpkin_get_metadata_t get_metadata;
pumpkin_on_load_t on_load;
pumpkin_on_unload_t on_unload;
} pumpkin_plugin_t;
void pumpkin_register_plugin(pumpkin_plugin_t plugin);
#define REGISTER_PUMPKIN_PLUGIN(plugin) \
void exports_plugin_init_plugin(void) { \
pumpkin_register_plugin(plugin); \
}
#ifdef __cplusplus
}
#endif
#endif

4606
src/gen/plugin.c Normal file

File diff suppressed because it is too large Load Diff

2369
src/gen/plugin.h Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

63
src/pumpkin_api.c Normal file
View File

@ -0,0 +1,63 @@
#include "pumpkin_api.h"
#include <stdlib.h>
#include <string.h>
static pumpkin_plugin_t g_plugin = {0};
void pumpkin_register_plugin(pumpkin_plugin_t plugin) {
g_plugin = plugin;
}
// WIT exports
void exports_pumpkin_plugin_metadata_get_metadata(exports_pumpkin_plugin_metadata_plugin_metadata_t *ret) {
if (g_plugin.get_metadata) {
pumpkin_metadata_t meta = g_plugin.get_metadata();
plugin_string_dup(&(ret->name), meta.name);
plugin_string_dup(&(ret->version), meta.version);
ret->authors.len = meta.authors_count;
ret->authors.ptr = (plugin_string_t*)malloc(ret->authors.len * sizeof(plugin_string_t));
for (size_t i = 0; i < ret->authors.len; ++i) {
plugin_string_dup(&(ret->authors.ptr[i]), meta.authors[i]);
}
plugin_string_dup(&(ret->description), meta.description);
ret->dependencies.len = meta.dependencies_count;
ret->dependencies.ptr = (plugin_string_t*)malloc(ret->dependencies.len * sizeof(plugin_string_t));
for (size_t i = 0; i < ret->dependencies.len; ++i) {
plugin_string_dup(&(ret->dependencies.ptr[i]), meta.dependencies[i]);
}
}
}
bool exports_plugin_on_load(plugin_own_context_t context_handle, plugin_string_t *err) {
if (g_plugin.on_load) {
g_plugin.on_load(context_handle);
return true;
}
return true; // No on_load is not an error
}
bool exports_plugin_on_unload(plugin_own_context_t context_handle, plugin_string_t *err) {
if (g_plugin.on_unload) {
g_plugin.on_unload(context_handle);
return true;
}
return true;
}
void exports_plugin_handle_event(uint32_t event_id, plugin_own_server_instance_t server, plugin_event_t *event, plugin_event_t *ret) {
// Basic event pass-through
*ret = *event;
}
bool exports_plugin_handle_command(uint32_t command_id, plugin_own_command_sender_t sender, plugin_own_server_instance_t server, plugin_own_consumed_args_t args, int32_t *ret, plugin_command_error_t *err) {
err->is_err = true;
plugin_string_dup(&(err->val.err.val.command_failed.val.text), "Command not implemented");
return false;
}
void exports_plugin_handle_task(uint32_t handler_id, plugin_own_server_instance_t server) {
}

1
wit/repo Submodule

@ -0,0 +1 @@
Subproject commit 7cc4854078e8a4008253b2e3bc7dc89db0ef37d3