Skip to content

시작하기

지원 Minecraft Script API 버전

Kairo는 Minecraft의 안정(stable) Script API가 필요합니다:

  • @minecraft/server 2.0.0 이상
  • @minecraft/server-ui 2.0.0 이상

2.0.0 이전 버전은 초기화 모델이 다르며(예: WorldLoad 대신 WorldInitialize 사용), 지원되지 않습니다.

kairo 설치

kairo 비헤이비어 팩을 월드에 추가하세요. 모든 애드온 간의 통신 허브 역할을 합니다.

kairo는 GitHub Releases에서 다운로드할 수 있습니다.

Kairo는 월드별 설정이 필요 없습니다. 같은 월드에 여러 Kairo 버전이 있어도 Kairo가 active host 하나를 자동으로 선택합니다. 애드온 코드는 계속 @kairo-js/router에만 의존하면 되며, 어떤 Kairo 팩 인스턴스가 호스트인지 알 필요가 없습니다.

kairo-router 사용하기

다른 애드온과 통신하려면 kairo-router를 애드온에 추가하세요.

설치

bash
pnpm add @kairo-js/router @kairo-js/properties

@kairo-js/router는 애드온 간 통신을 위한 runtime API입니다. @kairo-js/propertiesrouter.init()에 전달하는 AddonProperties 타입과 manifest 메타데이터에 맞는 구조를 제공합니다.

Kairo는 @kairo-js/utils도 제공합니다. router를 시작하는 데 필수는 아니지만 SemVer 유틸리티, seeded random, JSON parse helper, TypeBox compile helper 같은 공통 도구를 사용할 수 있습니다.

시작 이벤트에서 API 선언하기

모든 API 등록과 훅 선언은 반드시 router.beforeEvents.startup 내부에서 이루어져야 합니다.

typescript
import { router } from '@kairo-js/router'
import type { AddonProperties } from '@kairo-js/properties'
import { properties } from './properties'

router.beforeEvents.startup.subscribe((ev) => {
  // Register an API your addon provides
  ev.addonApi.register<{ playerId: string }, { balance: number }>(
    'economy/getBalance',
    async ({ playerId }) => ({ balance: 100 }),
  )
})

router.init(properties)

Minecraft custom component 등록

Minecraft custom component도 router.beforeEvents.startup 안에서 등록합니다. startup event에 노출된 native registry를 그대로 사용하세요.

typescript
router.beforeEvents.startup.subscribe((ev) => {
  ev.itemComponentRegistry.registerCustomComponent('my:item_component', {
    onUse(event) {
      console.log(event.source?.name)
    },
  })

  ev.blockComponentRegistry.registerCustomComponent('my:block_component', {
    onPlayerInteract(event) {
      console.log(event.player?.name)
    },
  })
})

다른 애드온의 API 호출하기

typescript
// fire-and-forget
router.send('economy-addon', 'onTransaction', { amount: 50 })

// await result
const result = await router.request<{ balance: number }>(
  'economy-addon',
  'getBalance',
  { playerId: '...' },
)

if ('canceled' in result) {
  console.log(result.reason)
} else {
  console.log(result.balance)
}

전체 API는 kairo-router API 레퍼런스를 참고하세요.

필수 dependencies

properties.ts"kairo"를 필수 dependency로 선언해야 합니다. 누락된 경우 router.init()이 즉시 오류를 발생시킵니다.

typescript
import type { AddonProperties } from '@kairo-js/properties'

export const properties: AddonProperties = {
  id: 'my-addon',
  dependencies: {
    kairo: '^1.0.0',
    // optional: 'kairo-database': '^2.0.0' — router.save/load/delete/has에 필요
  },
}

활성화에 필수적이지 않은 통합은 optionalDependencies에 작성하세요. 예를 들어 router.save(), router.load(), router.delete(), router.has()kairo-databasedependencies 또는 optionalDependencies 중 하나에 포함되어 있어야 사용할 수 있습니다.

커스텀 커맨드

커스텀 커맨드는 Minecraft native registry에 직접 등록하지 말고, router.beforeEvents.startup 안에서 ev.customCommandRegistry를 통해 등록하세요.

Minecraft는 일반적으로 같은 id의 커스텀 커맨드를 여러 개 등록하는 것을 거부합니다. 이 때문에 같은 월드에 여러 애드온 버전이 있으면 한 버전만 커맨드를 등록할 수 있습니다. Kairo-router는 커맨드 등록을 래핑하여 중복 native 등록을 안전하게 건너뛰고, Kairo가 실행을 현재 active인 애드온 버전으로 라우팅하게 합니다. 따라서 월드에서 버전을 전환해도 같은 command id를 유지한 커맨드를 계속 사용할 수 있습니다.

Command id와 인수 타입 순서는 호환성 계약입니다. 한 번 릴리스한 커맨드는 같은 command id에서 정렬된 인수 타입을 바꾸지 마세요. 인수 이름은 문서 메타데이터이므로 변경할 수 있습니다. 예를 들어 target: stringplayer: string으로 바꾸는 것은 호환됩니다. 타입 순서를 바꾸거나, 기존 인수 앞에 새 필수 인수를 추가하거나, 인수를 string에서 entity로 바꾸는 것은 호환되지 않습니다.

호환되지 않는 커맨드 시그니처가 필요하다면 major 버전을 올리고, 이전 시그니처를 사용하는 낮은 버전을 제거해야 한다는 점을 사용자에게 안내하세요. 또는 새 command id를 추가하고 기존 월드를 위해 오래된 커맨드를 유지할 수 있습니다.

스탠드얼론 모드

router.init(){ standalone: true }를 전달하면 스탠드얼론 활성화가 켜집니다. kairo가 설치되지 않은 경우, 필수 dependencies가 kairokairo-database만 포함되어 있으면 자동으로 활성화됩니다. kairo의 라이프사이클 관리를 선택적으로 활용하는 단독 애드온에 유용합니다.

자세한 내용은 RouterInitOptions를 참조하세요.

초기화 타이밍

월드 로드 후 kairo는 Discovery · Registration · Activation 초기화 플로우를 실행한 뒤 addonActivate를 발생시킵니다. 설치된 애드온 수에 따라 다르지만 약 30〜50틱의 지연이 발생합니다.

이 지연은 의도된 것입니다. Minecraft Script API 2.0.0+에서는 WorldLoad 완료 전에 world 관련 메서드를 호출하면 오류가 발생하는데, addonActivate는 그 대체 안전 신호 역할을 합니다.

typescript
router.afterEvents.addonActivate.subscribe(() => {
  // 여기서부터 world 메서드 호출 및 다른 애드온 API 사용이 안전합니다
})

TIP

바닐라 Script API 애드온에 익숙한 경우, addonActivateWorldLoad의 대체로 생각하세요. 추가 틱은 kairo의 핸드셰이크 비용이며, 낭비되는 시간이 아닙니다.

Released under the MIT License.