Mga gabay

Kotlin at Java

Para sa malalaking mod. Parehong API ng CraftScript, may static type, buong IDE at anumang Java library, at ilang bahagi na dito lang muna meron. Kotlin ang ginagamit ng gabay na ito; pareho ang paraan sa Java at ipinapakita ito sa dulo.

Ang kaya mong gawin

Bahagi Sa API Sa CraftScript
Mga item, block, recipe ContentBuilder: item, block, shaped, shapeless, smelting Oo
Mga nilalang ContentBuilder.creature: katawan, texture, stats, Behaviour, TargetRule, loot, kusang paglitaw, pagpapaamo, pagpaparami, pagsakay, sariling behaviour Oo
Mga tunog at partikulo ContentBuilder.sound, ContentBuilder.particle Oo
World generation ContentBuilder: ore, tree, patch, structure (mga pool, plan/build), biome, dimension, feature, terrain, biomes, carver, tag. Tingnan ang World generation at Paglikha gamit ang code Lahat maliban sa feature, tag, salt at aboveBottom
Interface Form at player.showForm; server.bossBar; player.setSidebar Oo
Mga kaganapan Crafting.events.on<E> { }, may priority at cancellation Oo
Mga effect, attribute, kagamitan addEffect, attribute, setAttribute, equipment, setEquipment, EquipmentSlot Yes
Mga key ContentBuilder.key, PlayerKeyEvent Yes
Mga command Crafting.commands.command(…): subcommand, typed na argument, permission, alias Oo
Mundo at mga player World, Block, Entity, Player, Inventory, Server Oo
Mga task Crafting.scheduler: runLater, runRepeating, runAsync, runSync Walang trabaho sa background
Settings sa file Typed na Config sa TOML, puwedeng i-sync sa mga client Oo (config)
Networking Crafting.network.channel(…), may sariling codec Oo (listen, send)
Saved data player.data["rubies.visits"] = n, data.getInt(…); pati sa mga entity, block at mundo Oo
Mga Java library Kahit ano ang gusto mo Hindi

Ang wala pa sa API ay wala sa anumang wika. Huwag itong lusutan sa pagtawag sa mga class ng Minecraft: mawawala sa mod ang garantiya na patuloy itong gagana kapag nagbago ang laro.

Gawin ang proyekto

Terminal
crafting new rubies --kind kotlin
cd rubies && gradle build

Wala pa sa public na Maven repository ang API. I-install ito sa local Maven mo mula sa source ng Crafting at ideklara ito bilang compileOnly: ibinibigay ito ng Crafting sa mod habang tumatakbo.

Terminal
cd crafting && ./gradlew :crafting-api:publishToMavenLocal
build.gradle.ktsKotlin
plugins { kotlin("jvm") version "2.4.21" }

repositories { mavenCentral(); mavenLocal() }

dependencies {
    compileOnly("dev.crafting:crafting-api:0.1.0")
}

kotlin { jvmToolchain(25) } // Tumatakbo ang Minecraft 26.x sa Java 25

Ginagawa ng crafting new ang file na ito at isang proyektong nakahati na ayon sa responsibilidad: <Name>Mod.kt, na nagkakabit lang ng mga bahagi, content/ModContent.kt, events/Welcome.kt at commands/GemCommand.kt.

Istruktura

Mga package ayon sa paksa, isang entry class na nagkakabit lang ng mga bahagi, at isang file bawat bahagi. Ipinapaliwanag ng gabay na Pag-aayos ng mod kung bakit; narito ang buong halimbawang mod:

IstrukturaText
rubies/
├── build.gradle.kts
├── settings.gradle.kts
└── src/main/
    ├── kotlin/com/example/rubies/
    │   ├── RubiesMod.kt         entry point: only wires the parts
    │   ├── RubiesConfig.kt      player settings
    │   ├── content/
    │   │   ├── Items.kt
    │   │   ├── Blocks.kt
    │   │   ├── Creatures.kt
    │   │   ├── Sounds.kt
    │   │   ├── Particles.kt
    │   │   └── Recipes.kt
    │   ├── storage/
    │   │   └── Visits.kt        saved data: the keys, in one place
    │   ├── events/
    │   │   ├── MiningEvents.kt
    │   │   ├── CombatEvents.kt
    │   │   └── WelcomeEvents.kt
    │   ├── ui/
    │   │   └── ShopForm.kt       forms: what the player sees
    │   └── commands/
    │       ├── RubyCommand.kt
    │       └── ShopCommand.kt
    └── resources/
        ├── crafting.mod.json
        └── assets/rubies/
            ├── sounds/ruby/chime.ogg
            └── textures/
                ├── item/ruby.png
                ├── entity/ruby_golem.png
                └── particle/ruby_spark_0.png, ruby_spark_1.png

src/main/kotlin/com/example/rubies/

Walang ginagawa nang mag-isa ang entry class: ginagawa nito ang mga shared at tinatawag ang bawat bahagi.

src/main/kotlin/com/example/rubies/RubiesMod.ktKotlin
package com.example.rubies

class RubiesMod : CraftingMod {
    override fun onLoad(ctx: ModContext) {
        val config = Crafting.configs.load(RubiesConfig())
        val content = ContentBuilder(ctx.metadata.id, Crafting.registries)

        Items.register(content)
        Blocks.register(content)
        Creatures.register(content)
        Sounds.register(content)
        Particles.register(content)
        Recipes.register(content)

        MiningEvents.register(config)
        CombatEvents.register(config)
        WelcomeEvents.register()
        RubyCommand.register()
        ShopCommand.register()
    }
}

Ang manifest

src/main/resources/crafting.mod.jsonJSON
{
  "id": "rubies",
  "name": "Rubies",
  "version": "1.0.0",
  "kind": "mod",
  "side": "both",
  "entrypoints": ["com.example.rubies.RubiesMod"],
  "depends": { "crafting": ">=0.1.0" }
}
Patlang Ano ito
id 2–64 na character: maliliit na titik, digit, _ o -, nagsisimula sa titik. Ito rin ang namespace ng mga item at block mo.
kind mod o plugin (server lang, nare-reload; tingnan sa ibaba).
side both, client o server. Tahimik na hindi pinapansin ang client mod sa dedicated server.
entrypoints Ang mga class na nag-i-implement ng CraftingMod.
depends, optional, incompatible Id → range ng bersyon: >=1.2 <2, ^1.4, ~1.4.2, 1.20.x, [1.0,2.0). Kung may pumalya, sabay-sabay na iniuulat ng Crafting ang bawat problema, may mungkahi.
loadAfter, loadBefore Pagkakasunod ng pag-load nang walang mahigpit na dependency.

Siklo ng buhay

dev.crafting.api.mod.CraftingModKotlin
interface CraftingMod {
    fun onLoad(ctx: ModContext)
    fun onReady(ctx: ModContext) {}
    fun onShutdown(ctx: ModContext) {}
}
  1. onLoad: i-register ang content, mga event at mga command.
  2. Ginagawa ng Crafting ang mga block at item sa laro. Mula rito, nagthi-throw ng RegistryFrozenException ang pag-register ng content.
  3. onReady: naka-load na ang lahat ng mod; sinasabi ng Crafting.runtime.isModLoaded("other_mod") kung may ibang mod.
  4. onShutdown: sa paglabas.

Mga plugin ng server

Ang plugin ay isang CraftingMod na may "kind": "plugin" at "side": "server"; ginagawa ng crafting new chatguard --kind plugin ang entry class, events/ChatFilter.kt at commands/HelloCommand.kt. Hindi ito nagdadagdag ng block o item, kaya makakapasok ang mga player na may Minecraft na walang mod sa server na plugin lang ang meron. Ine-enable, dini-disable at nire-reload mo ito nang hindi nagre-restart: tumatakbo ang onLoad at onReady kapag na-enable ito, at ang onShutdown kapag na-disable o na-reload ito.

Terminal
crafting new chatguard --kind plugin
src/main/kotlin/com/example/chatguard/ChatGuardPlugin.ktKotlin
package com.example.chatguard

class ChatGuardPlugin : CraftingMod {
    override fun onLoad(ctx: ModContext) {
        ChatFilter.register()
        Crafting.commands.command("guard") {
            permission = "chatguard.admin"
            executes { it.reply("Aktibo ang ChatGuard") }
        }
    }

    override fun onShutdown(ctx: ModContext) = ctx.logger.info("Na-disable ang ChatGuard")
}
src/main/kotlin/com/example/chatguard/events/ChatFilter.ktKotlin
package com.example.chatguard.events

object ChatFilter {
    private val blocked = listOf("spam", "scam")

    fun register() {
        Crafting.events.on<PlayerChatEvent> { e ->
            if (blocked.any { it in e.message.lowercase() }) {
                e.cancel()
                e.player.send("&cMaging magalang po tayo")
            }
        }
    }
}

Nakatali sa plugin ang lahat ng nire-register nito. Tinatawag ng /crafting reload chatguard ang onShutdown, inaalis ang mga listener, command at task nito, binabasa muli ang jar at tinatawag ang onLoad. Sa development mode, awtomatiko itong nangyayari kapag pinalitan mo ang jar.

Mod Plugin
Folder mods/ plugins/
Side Client at/o server Server lang
Bagong block at item Oo Hindi
Reload nang walang restart Hindi Oo
Makakapasok ang client na walang mod Hindi, kung nagdadagdag ito ng content Oo

Java

Parehong API, parehong istruktura. Mula sa Java, Crafting.INSTANCE ang entry point, ipinapasa mo ang bawat parameter na may default value, at nagre-return ng Unit.INSTANCE ang listener:

src/main/java/com/example/rubies/RubiesMod.javaJava
package com.example.rubies;

public final class RubiesMod implements CraftingMod {
    @Override
    public void onLoad(ModContext ctx) {
        ContentBuilder content = new ContentBuilder(ctx.getMetadata().getId(), Crafting.INSTANCE.getRegistries());
        Items.register(content);
        WelcomeEvents.register();
    }
}
src/main/java/com/example/rubies/events/WelcomeEvents.javaJava
package com.example.rubies.events;

public final class WelcomeEvents {
    public static void register() {
        Crafting.INSTANCE.getEvents().subscribe(PlayerJoinEvent.class, EventPriority.NORMAL, false, null, e -> {
            e.getPlayer().send("&aWelcome, " + e.getPlayer().getName() + "!");
            return Unit.INSTANCE;
        });
    }
}

Mga lumang paraan

Gumagana pa rin ang mga ito, pero minarkahan silang deprecated at may kapalit:

Dati Ngayon
class X : CraftingPlugin() na may onEnable/onDisable CraftingMod na may "kind": "plugin"
Mga method na may @Subscribe at events.register(obj) events.on<E> { } (Java: events.subscribe(E.class, …))
@Mod("id") sa class Ang class sa entrypoints ng manifest
EntityDamageEvent.source damageType (isang id, gaya ng minecraft:fall)
world.setBlockState(x, y, z, "…[open=true]") world.setBlock(x, y, z, type, mapOf("open" to true))

Mga patakaran

  • Huwag mag-import ng anuman mula sa net.minecraft. Iyan ang nagpapanatiling gumagana ng mod kapag nagbago ang laro.
  • Sa onLoad lang mag-register ng content.
  • Hindi ginagalaw ng task na runAsync ang mundo; bumalik sa thread ng laro gamit ang runSync.