This commit is contained in:
2026-09-24 23:28:01 -03:00
parent 79faa556de
commit bb42dd662e
73 changed files with 2349 additions and 34 deletions
+3
View File
@@ -0,0 +1,3 @@
# Example Mod
Made by you. List where textures and other assets come from and their licenses here.
+31
View File
@@ -0,0 +1,31 @@
# Example Mod
A bworld mod. The format is described in `MODS.md` at the root of the bworld repo.
## Files
| Path | What it's for |
| --------------------- | ------------------------------------------------------------------------------------ |
| `manifest.json` | The mod's id, name, version, dependencies and scripts. |
| `blocks/*.json` | One block per file. Blocks get an item form with the same id unless `"item": false`. |
| `items/*.json` | Items that aren't a block's item form. |
| `recipes/*.json` | `shaped` crafting, `furnace` smelting and `fuel`. |
| `textures/*.png` | 16×16 textures, named `example_mod:<file name>`. |
| `worldgen/ores.json` | Ores to generate (optional, not included here). |
| `scripts/server.ts` | Game logic: block components, commands, events. Never sent to players. |
| `scripts/client.ts` | Sent to players: custom screens, HUD, keybinds. |
| `scripts/worldgen.ts` | Terrain features. Runs on the server and every client and must be deterministic. |
| `CREDITS.md` | Licenses and thanks, shown on the About page. |
Delete what you don't use, including its entry in `manifest.json`.
## Checking it
From the bworld repo:
```sh
deno task check-mods
```
This validates the manifest and every data file, checks that the ids, textures and items you refer to exist, and
typechecks the scripts.
+13
View File
@@ -0,0 +1,13 @@
{
"format_version": 1,
"block": {
"id": "example_mod:example_block",
"textures": "example_mod:example_block",
"mining": { "toughness": 3, "tool": "pickaxe", "requires_tool": false },
"drops": "example_mod:example_block",
"interactive": true,
"components": {
"example_mod:announce": { "message": "You found the example block!" }
}
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"format_version": 1,
"item": {
"id": "example_mod:example_item",
"texture": "example_mod:example_item",
"lore": "Four of these make an example block."
}
}
+18
View File
@@ -0,0 +1,18 @@
{
"format_version": 1,
"id": "example_mod",
"name": "Example Mod",
"description": "What this mod adds, in a sentence or two.",
"version": "0.1.0",
"authors": [],
"game_version": ">=0.1.0",
"dependencies": [
{ "id": "bworld", "version": ">=0.1.0" }
],
"scripts": {
"server": "scripts/server.ts",
"client": "scripts/client.ts",
"worldgen": "scripts/worldgen.ts"
},
"credits": "CREDITS.md"
}
+9
View File
@@ -0,0 +1,9 @@
{
"format_version": 1,
"recipe": {
"type": "shaped",
"pattern": ["EE", "EE"],
"key": { "E": "example_mod:example_item" },
"result": { "id": "example_mod:example_block", "count": 1 }
}
}
+14
View File
@@ -0,0 +1,14 @@
import type { ClientContext } from "bworld/client";
// called on every player's client after the mod is downloaded, before the world shows up.
// everything here is visible to players, so keep secrets and game rules in server.ts
export function setup(ctx: ClientContext) {
ctx.log("loaded");
// a HUD element, drawn every frame
// ctx.hud.register("example_mod:hint", {
// on_render(g) {
// g.text("example mod is here", 8, 8);
// },
// });
}
+26
View File
@@ -0,0 +1,26 @@
import type { ServerContext } from "bworld/server";
// called once when the server starts
export function setup(ctx: ServerContext) {
// used by blocks/example_block.json, which passes { message } as params
ctx.components.register_block<{ message: string }>("example_mod:announce", {
on_interact(_block, params, player) {
player.send_message(params.message);
// handled, so right clicking it doesn't place a block
return true;
},
});
// /example_mod:hello, or /hello when no other mod uses that name
ctx.commands.register("hello", {
description: "Say hello",
usage: "/hello",
run(_args, player) {
player.send_message(`Hello ${player.name}!`);
},
});
ctx.events.after.player_join.subscribe(({ player }) => {
ctx.log(`${player.name} joined`);
});
}
+15
View File
@@ -0,0 +1,15 @@
import type { WorldgenContext } from "bworld/worldgen";
// runs in chunk workers on the server and every client, which must all generate the same world.
// only use chunk.rng and the noise helpers, never Math.random or the time
export function setup(gen: WorldgenContext) {
// a boulder on one chunk in ten
gen.register_feature("example_mod:boulders", (chunk) => {
if (chunk.rng.next() > 0.1) {
return;
}
const x = chunk.x * 16 + Math.floor(chunk.rng.next() * 16);
const z = chunk.z * 16 + Math.floor(chunk.rng.next() * 16);
chunk.set_block(x, chunk.height_at(x, z) + 1, z, "bworld:stone");
});
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B