Luaスクリプティング: プロップAPI
このページでは、FreeMinecraftModelsのプロップスクリプトで使うcontext.prop、context.event、context.player、context.projectile、context.world、context.zones、context.scheduler、context.state、context.cooldowns、context.logを説明します。初めての場合ははじめにを参照してください。
context.prop
プロップの情報とアニメーション操作を提供します。FMMはこのテーブルをプロップごとにキャッシュします。current_locationは読み取り時に取得するため、現在の位置を反映します。
フィールド
| フィールド | 型 | 説明 |
|---|---|---|
prop.model_id | string | ブループリントのモデル名。例: "torch_01" |
prop.current_location | locationテーブル | 読み取り時のプロップの位置。固定のスナップショットではありません |
位置テーブルにはx、y、z、world、yaw、pitchがあります。
例: プロップの情報を読む
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop spawned: " .. (context.prop.model_id or "unknown"))
local loc = context.prop.current_location
if loc then
context.log:info("Location: " .. loc.x .. ", " .. loc.y .. ", " .. loc.z)
end
end
}
prop:play_animation(name, blend, loop)
プロップのモデルに名前を指定してアニメーションを要求します。
| 引数 | 型 | 既定値 | 説明 |
|---|---|---|---|
name | string | 必須 | モデルファイル内のアニメーション名 |
blend | boolean | true | trueは現在の状態のtick後に切り替えを予約、falseは即時割り込み。クロスフェードではありません |
loop | boolean | true | カスタムアニメーションの繰り返し。組み込み状態には独自の規則があります |
要求を受け付けるとtrue、受け付けられないとfalseを返します。待機中や抑制された要求も受け付けたものに含まれます。終端のdeath状態は追加要求を拒否します。カスタムアニメーション中の攻撃要求は、それを中断せずに受け付けます。待機枠は1つだけで、新しい待機要求が前のものを置き換えます。trueだけでは画面上の再生を確認できません。アニメーションを参照してください。
例
return {
api_version = 1,
on_right_click = function(context)
local success = context.prop:play_animation("open", true, false)
if not success then
context.log:warn("Animation 'open' not found on this model!")
end
end
}
prop:stop_animation()
待機要求を消去して、idleがあれば戻ります。なければ共有エンジンの現在の状態を停止します。終端のdeath状態は維持されますが、Bedrock側には停止要求を送ります。引数はありません。
例
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
prop:hurt_visual()
実際のダメージを与えずに赤い被ダメージ表示を再生します。引数はありません。
例
return {
api_version = 1,
on_left_click = function(context)
-- Flash red when punched, but don't actually take damage
if context.event then
context.event.cancel()
end
context.prop:hurt_visual()
end
}
prop:pickup()
プロップを削除し、その位置に配置用の紙アイテムを落とします。紙でブロックを右クリックすると再配置できます。
引数も戻り値もありません。削除とドロップはBukkitのメインスレッドに予約します。権限確認は行わず、保存済みのインベントリや本のデータも紙へ移しません。呼び出し側でアクセスを確認し、保存内容を先に処理してください。回収が予約済みの間はpickup()を繰り返さないでください。
例
return {
api_version = 1,
on_right_click = function(context)
-- Let players pick up the prop by right-clicking it
context.prop:pickup()
end
}
prop:mount(player)
最初の空いている座席にプレイヤーを乗せます。モデルにはマウントポイントのボーンが必要です。
| 引数 | 型 | 説明 |
|---|---|---|
player | entityテーブル | context.playerやcontext.event.playerなどのプレイヤー |
プレイヤーが見つかり、プロップにマウントポイントがあり、乗車を予約できるとtrueを返します。基本参照が無効ならfalseです。trueでも実行時に空席があるとは限りません。
右クリックのスクリプトが座席を操作する場合は、context.eventをキャンセルしてください。FMMの既定処理も同時に乗車を試みるのを防ぎます。
例
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player then
context.prop:mount(player)
end
end
}
prop:dismount(player)
プロップの座席からプレイヤーを降ろします。
| 引数 | 型 | 説明 |
|---|---|---|
player | entityテーブル | プレイヤー |
プレイヤーが見つかり、マウントマネージャーがあり、降車確認を予約できるとtrue、基本参照が無効ならfalseを返します。
例
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player then
-- Toggle mount/dismount
local passengers = context.prop:get_passengers()
for i = 1, #passengers do
if passengers[i].uuid == player.uuid then
context.prop:dismount(player)
return
end
end
context.prop:mount(player)
end
end
}
prop:get_passengers()
現在の乗員のentityテーブルをLua配列で返します。引数はありません。
例
return {
api_version = 1,
on_game_tick = function(context)
local passengers = context.prop:get_passengers()
if #passengers > 0 then
context.log:info("Prop has " .. #passengers .. " passenger(s)")
end
end
}
prop:has_mount_points()
モデルにマウントポイントのボーンがあるかをtrueまたはfalseで返します。引数はありません。
例
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player and context.prop:has_mount_points() then
context.prop:mount(player)
end
end
}
prop:spawn_elitemobs_boss(filename, x, y, z)
指定位置にEliteMobsのカスタムボスを生成します。EliteMobsが必要です。
| 引数 | 型 | 説明 |
|---|---|---|
filename | string | ボスのファイル名。例: "my_boss.yml" |
x | number | X座標 |
y | number | Y座標 |
z | number | Z座標 |
生成したボスのliving entityテーブルを返します。プラグインが利用できない、設定がない、生成に失敗したなど、連携が生きているボスを返せない場合はnilです。nilだけでは原因を特定できません。
例
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local boss = context.prop:spawn_elitemobs_boss("dungeon_guardian.yml", loc.x, loc.y + 1, loc.z)
if boss then
context.log:info("Spawned boss: " .. (boss.name or "unknown"))
else
context.log:warn("Could not spawn boss -- is EliteMobs installed?")
end
end
end
}
prop:open_inventory(player, title, rows)
チェストインベントリのGUIを開く処理を予約します。各プロップは共有のインベントリを1つ持ちます。最初に開いたときにプロップのPersistentDataContainerに保存された内容から作成され、以降に開くとすべての閲覧者に同じライブのインベントリが表示されます。FMMは、最後の閲覧者が閉じたとき、プロップのチャンクがアンロードされたとき、そしてdrop_inventory()が読み取る前に、その内容をプロップへ保存します。
| 引数 | 型 | 既定値 | 説明 |
|---|---|---|---|
player | entityテーブル | 必須 | 表示するプレイヤー |
title | string | 必須 | タイトル。&の色コードに対応 |
rows | int | 3 | 1〜6行。6行は54スロットのダブルチェスト相当 |
プロップとプレイヤーの参照が有効で、開く処理を予約できればtrue、それ以外はfalseです。行数は作成前に1〜6へ制限します。
サイズとタイトルは、インベントリを作成した呼び出しのものが使われます。開いている間は、後の呼び出しも同じインベントリをそのまま再利用します。保存された内容が要求した行数より多くのスロットを持つ場合、インベントリはそれが収まるサイズに拡張されるため、小さいrowsを指定しても保存済みのアイテムが失われることはありません。保存データを読み取れない場合、インベントリは開きません。処理の実行前にプロップが削除されていた場合、その処理はスキップされます。戻り値はインベントリが開いたことを保証しません。
prop:is_viewing_inventory(player)
インベントリのリスナーが、このプロップの閲覧者としてプレイヤーを追跡しているかを返します。実際にGUIが開いたままである保証ではありません。
| 引数 | 型 | 説明 |
|---|---|---|
player | entityテーブル | 確認するプレイヤー |
trueまたはfalseを返します。
例: インベントリを閉じた後のアニメーション
context.state["task_" .. player.uuid] = context.scheduler:run_repeating(5, 5, function(tick_context)
if not tick_context.prop:is_viewing_inventory(player) then
tick_context.prop:play_animation("close", true, false)
tick_context.scheduler:cancel(tick_context.state["task_" .. player.uuid])
end
end)
prop:place_book(player)
メインハンドの記入済みまたは記入可能な本をプロップに保存します。
| 引数 | 型 | 説明 |
|---|---|---|
player | entityテーブル | 本を持つプレイヤー |
参照が有効で処理を予約できるとtrueを返します。後のメインスレッド処理は、対象の本を持ち、プロップにまだ本がない場合だけ保存します。
prop:read_book(player)
保存した本をプレイヤーに開きます。
| 引数 | 型 | 説明 |
|---|---|---|
player | entityテーブル | 本を表示するプレイヤー |
参照が有効で閲覧を予約できるとtrueを返します。実行時には、保存済みでデシリアライズ可能なWRITTEN_BOOKが必要です。保存済みでもWRITABLE_BOOKは開きません。
prop:take_book(player)
保存した本をプレイヤーのインベントリに戻し、プロップから削除します。
| 引数 | 型 | 説明 |
|---|---|---|
player | entityテーブル | 本を受け取るプレイヤー |
参照が有効で取り出しを予約できるとtrueを返します。本が存在する保証ではありません。
プレイヤーのインベントリに空きを確保してください。追加前に保存レコードを削除し、入りきらない分をドロップしません。place_bookは手持ちスタック全体を保存してから1個減らすため、通常の1冊だけの本を使ってください。
prop:has_book()
基底のアーマースタンドのPDCに本のキーがあるかだけを調べます。保存内容の妥当性は検証しません。引数はありません。
prop:drop_inventory()
開いているインベントリがあれば保存してすべての閲覧者に対して閉じ、その後に保存済みの内容を読み取り、PDCのレコードを消してからアイテムをプロップの位置に落とす処理を予約します。その時点までに開いているインベントリで行われた変更も含まれます。レコードの削除後に復元に失敗すると、ドロップするアイテムがなくなることがあります。
引数はありません。有効な基底アーマースタンドがあり、処理を予約できるとtrueを返します。保存済みアイテムの存在は保証しません。
prop:drop_book()
保存した本をプロップの位置に落とす処理を予約します。復元前に保存レコードを削除するため、復元に失敗すると本を失うことがあります。
引数はありません。有効な基底アーマースタンドがあり、処理を予約できるとtrueを返します。本の存在は保証しません。
prop:set_persistent_data(key, value)
プロップのアーマースタンドのPersistentDataContainerに文字列を保存します。通常のワールド保存やチャンクのアンロードでは、そのアーマースタンドとともに保持されます。プロップの完全削除や配置用の紙への置き換えでは移し替えません。
| 引数 | 型 | 説明 |
|---|---|---|
key | string | 小文字、数字、._-/からなる有効なBukkitキーの末尾。内部ではfmm_lua_<key>として保存し、無効な文字はエラーになります |
value | string | 保存する値。数値や真偽値にはtostring()を使用 |
成功時はtrue、基底アーマースタンドがなければfalseを返します。
prop:get_persistent_data(key)
set_persistent_dataで保存した文字列を読みます。未設定ならnilです。
| 引数 | 型 | 説明 |
|---|---|---|
key | string | 保存時に使ったキー |
例: 切り替え状態の保存
return {
api_version = 1,
on_spawn = function(context)
local saved = context.prop:get_persistent_data("active")
context.state.active = saved == "true"
end,
on_right_click = function(context)
context.state.active = not context.state.active
context.prop:set_persistent_data("active", tostring(context.state.active))
end
}
アイテム効果
装備アイテム用のcontext.item APIは廃止されました。カスタムエンチャントで効果を定義し、アイテムのenchantments:リストに名前空間付きIDで関連付けてください。
context.event
現在のフックのイベントデータです。プロップのクリック、投射物の命中、汎用ゾーンのフックで利用できます。on_spawn、on_game_tick、on_destroyのように関連するイベントやプレイヤーがなければnilです。
FMMのクリックには、プロップの既定動作を取り消すプラグイン独自のフラグを使います。Luaで公開するのは以下のフィールドとメソッドだけです。
フィールドとメソッド
| フィールドまたはメソッド | 型 | 説明 |
|---|---|---|
event.player | player entityテーブル | クリックした、または監視ゾーンを出入りしたプレイヤー。on_left_click、on_right_click、on_zone_enter、on_zone_leaveで利用可能。on_projectile_hitでは投射物を発射した生物エンティティで、モブの場合もあります。発射者が生物エンティティでなければ存在しません。プレイヤーメソッドを参照 |
event.is_cancelled | boolean | コンテキスト作成時のキャンセル状態。cancel()やuncancel()後は更新されません |
event.cancel() | function | イベントを取り消し、既定のダメージや操作を防ぎます |
event.uncancel() | function | キャンセルを解除します |
cancelとuncancelは渡された引数を無視するため、context.event.cancel()とcontext.event:cancel()は同じ動作です。このページではドットを使いますが、どちらでも動きます。
汎用ゾーンのフックにはプレイヤーはありますがキャンセルフラグはありません。event.cancel()とevent.uncancel()は存在せず、event.is_cancelledはfalseです。プロップのクリックをキャンセルすると、対応するFMMの既定動作を防ぎます。
event.is_cancelledは初期状態のスナップショットです。同じフック内でキャンセル変更を後から参照する場合は、ローカル変数に記録してください。
target、block、projectile、itemなどのBukkit固有フィールドは公開しません。追加情報にはcontext.player、context.event.player、context.projectile(on_projectile_hit内)、player:get_target_entity(range)、context.world:raycast(...)や近くのエンティティの検索を使ってください。
on_projectile_hit
投射物がプロップのヒットボックスに当たったとき、投射物1つにつき1回呼ばれます。
| コンテキストの値 | 説明 |
|---|---|
context.projectile | 投射物(矢、トライデント、雪玉など)のエンティティテーブル。このフックでのみ設定されます |
context.event.player | 投射物を発射した生物エンティティ(いる場合) |
context.player | 発射者がプレイヤーの場合はその発射者、それ以外はnil |
このフックはFMMが命中を処理した後に実行され、FMMの既定の投射物処理はプロップに対して何も行いません。ここでcontext.event.cancel()を呼んでも、貫通しない投射物が命中によって消費されるのは止められません。別のプラグインがすでに命中をキャンセルしていた場合、このフックは呼ばれません。
return {
api_version = 1,
on_projectile_hit = function(context)
local shooter = context.player
if shooter then
shooter:send_message("&eYou hit the target!")
end
context.prop:play_animation("hit", false, false)
end
}
例: 左クリックのダメージを防ぐ
例
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
例: キャンセル状態の確認
例
return {
api_version = 1,
on_left_click = function(context)
if context.event and not context.event.is_cancelled then
context.event.cancel()
context.log:info("Damage cancelled!")
end
end
}
scheduler:run_laterやscheduler:run_repeatingのコールバックではcontext.eventは常にnilです。イベントを変更できるのはそのイベントフックの実行中だけです。
context.world
FreeMinecraftModels/MagmaCoreのワールドAPIです。完全な説明はcontext.worldにあります。
共通ページのget_block_at、set_block_at、spawn_particle、play_sound、strike_lightning、get_time、set_time、get_nearby_entities、get_nearby_players、spawn_entity、get_highest_block_y、raycast、place_temporary_block、drop_item、spawn_fireworkはすべてFMMで使えます。MagmaCoreのワールドAPIでは、エンティティやブロックを検出するworld:raycast()、一時的なブロック置換のworld:place_temporary_block()、色や形を指定するworld:spawn_firework()も説明しています。EliteMobsのボスパワーはこの共通基盤に、位置テーブルを使うボス、増援、落下ブロック、一時ブロックなどの操作を追加します。EliteMobsのワールドと環境を参照してください。
FMM固有のワールド拡張
FMMはcontext.worldにEliteMobsの戦利品用メソッドを3つ追加します。常に存在しますが、EliteMobsがなければ何もせずfalseを返します。
| メソッド | 説明 |
|---|---|
world:drop_elitemobs_procedural_loot(player, level, location?) | 自動生成の戦利品を作ります。EliteMobsのインベントリ直接付与設定に従い、入らない分はプレイヤーの位置に落とします。直接付与でなければ指定位置を使用。自動生成ドロップが無効ならfalse |
world:drop_elitemobs_random_loot(player, level, location?) | 指定レベルでプレイヤー用のEliteMobs戦利品テーブルを抽選します |
world:drop_elitemobs_custom_loot(player, file, level, location?) | 指定したEliteMobsカスタムアイテムをドロップします。ファイルを解決できなければfalse |
完全なシグネチャはLua APIリファレンスにあります。ボス生成には前述のprop:spawn_elitemobs_boss(...)を使います。
プレイヤーエンティティメソッド
context.player、context.event.player、context.world:get_nearby_players()がプレイヤーテーブルを返します。MagmaCoreの汎用on_zone_enterとon_zone_leaveでは、出入りしたプレイヤーを両方のコンテキストフィールドに設定します。
FMMは共通ページのエンティティ、living entity、プレイヤー、UIメソッドを使います。EliteMobsのボスパワーには類似したボス固有テーブルがあり、ボスとエンティティで説明しています。FMMのフィールドとメソッドはMagmaCore LuaエンジンとプレイヤーUIメソッドを参照してください。player:get_target_entity()のレイキャスト、player:get_eye_location()、player:get_look_direction()、プレイヤーだけに偽のブロックを見せるplayer:send_block_change()、player:reset_block()はプレイヤー固有メソッドにあります。
FMM固有のエンティティフィールド
FMMのLuaEntityEnricherが次のフィールドを追加します。フラグとモデル参照はテーブル作成時のスナップショットなので、モデルの関連付けを変更した後は新しいテーブルを取得してください。プレイヤーのhas_permissionは現在の権限を調べますが、is_opはスナップショットです。
| フィールド | 型 | 説明 |
|---|---|---|
entity.is_modeled | boolean | BukkitエンティティがModeledEntityの基底ならtrue |
entity.is_prop | boolean | PropEntityを支えるアーマースタンドならtrue |
entity.model | tableまたはnil | is_modeled = trueのときだけ設定 |
entity.modelには次のメンバーがあります。
| フィールドまたはメソッド | 説明 |
|---|---|
model.model_id | ブループリントのモデル名。例: "dragon" |
model.is_dynamic | living entityに付いたDynamicEntityならtrue |
model:play_animation(name, blend, loop) | アニメーションを要求します。この連携ではblendとloopの既定値はfalse。trueは要求受付を示し、画面上の再生は保証しません |
model:stop_animations() | 待機要求を消してidleがあれば戻ります。終端の死亡状態は中断しません |
model:remove() | モデル付きエンティティと全ボーンを即座に削除します |
on_right_click = function(context)
local player = context.event and context.event.player
if not player then return end
local target = player:get_target_entity(8)
if target and target.is_modeled then
target.model:play_animation("hurt", true, false)
end
end
EliteMobsのエンティティフィールド
EliteMobsがあれば、そのenricherを通じて以下も追加します。
| フィールド | 型 | 説明 |
|---|---|---|
entity.is_elite | boolean | EliteMobsが追跡するエンティティならtrue |
entity.is_custom_boss | boolean | カスタムボス設定ならtrue |
entity.is_significant_boss | boolean | healthMultiplier > 1のカスタムボスならtrue。名前付き雑魚を除外します |
entity.elite | tableまたはnil | is_elite = trueのとき設定。level、name、health、max_health、health_multiplier、damage_multiplier、is_custom_boss、elite:remove()を含みます |
フラグと大部分のeliteフィールドはスナップショットですが、healthとmax_healthは読み取り時に取得します。EliteMobs有効時のentity:can_receive_hostile_effect(player_uuid)は、共通の敵対対象確認後にEliteMobsの魔法対象の許可確認も行います。アダプターが利用できない場合は拒否し、味方を単独の対象として扱いません。
context.zones
FMM/MagmaCoreのゾーンAPIはcontext.zonesを参照してください。EliteMobsのボスパワーには独自のゾーン定義を使う別のテーブルがあります。EliteMobsのゾーンと対象選択を参照してください。
context.scheduler
FMMとEliteMobsのNPCスクリプトはMagmaCoreのスケジューラーを使います。run_after、run_every、cancel_taskも共通スケジューラーの別名なので使えます。ボスパワーも専用コンテキストから同じ別名を公開します。context.schedulerを参照してください。
context.state
FMM、EliteMobsのボスパワーとNPCスクリプトで共有する状態APIです。context.stateを参照してください。
context.log
FMM/MagmaCoreのロガーはinfo、warn、errorを提供します。EliteMobsのNPCも同じロガーを使い、ボスパワーはinfo、warn、debugを提供します。context.logを参照してください。
context.cooldowns
FMMとEliteMobsのNPCはMagmaCore共通の引数順check_local(key?, duration)を使います。ボスパワーも専用の保存領域で同じ順を使います。context.cooldownsを参照してください。
| メソッド | 説明 |
|---|---|
local_ready(key?) | ローカルの待機時間が終わったか確認 |
local_remaining(key?) | 残りtick数、または0を返す |
check_local(key?, duration) | ローカルの確認と開始を不可分に行う |
set_local(duration, key?) | 確認せずローカルの待機時間を設定 |
global_ready() | スクリプト所有者が共有するグローバルの待機時間を確認 |
set_global(duration) | グローバルの待機時間を設定 |
通常のプロップの操作にはcontext.cooldowns:check_local("my_key", 40)を使ってください。
実行モデル
スクリプトインスタンスごとのランタイム
プロップのscripts:リストの各項目に独立したLuaランタイムを作ります。FMMはプロバイダー登録時にソースを検出、検証し、各関連付けに対してキャッシュ済みソースを新しいサンドボックスで評価します。Luaファイルの変更や追加を新しい関連付けで使うには、再読み込みの成功が必要です。コールバックは設定リスト順で実行し、読み込んだpriorityで順序は変更しません。プロップを削除するとそのスクリプトインスタンスを終了します。
アイテムのエンチャントは別のライフサイクルで動き、装備アイテム用のプロップスクリプトインスタンスを作りません。
- ファイル内のローカル変数はインスタンス専用です。
- 同じファイルを使っていても
context.stateはインスタンス間で完全に分離されます。
予約タスクの所有者
context.schedulerで作ったタスクは、そのランタイムに属します。プロップを削除すると以下を行います。
- ランタイムを終了します。
- 単発と繰り返しの全所有タスクを自動キャンセルします。
- すべてのゾーン監視を解除します。
on_destroyが最初に実行されるのは、拾われた、壊された、/fmm deleteallで削除された、またはプラグインによって削除されたなど、プロップが完全に削除されたときだけです。プロップのチャンクやワールドがアンロードされたとき、またはFMMのリロードや停止時には、on_destroyを呼ばずにランタイムが停止します。チャンクが再び読み込まれると、プロップは新しいランタイムと新しいon_spawnとともに戻ってきます。
クールダウンの範囲
共通エンジンにはローカルのlocal_ready、local_remaining、check_local、set_localと、グローバルのglobal_ready、set_globalがあります。
| スクリプト | ローカルの範囲 | グローバルの範囲 |
|---|---|---|
| プロップ | プロップとスクリプトファイルのScriptInstanceごと | PropEntityごと。そのプロップのすべてのスクリプトで共有 |
プロップの登録解除時、または成功した再読み込みや無効化でスクリプトマネージャーが終了すると、グローバルの保存領域を消去します。再読み込みの準備が拒否された場合は現在のランタイムを保持します。クールダウンは単調増加する経過時間を使い、指定した1tickを50msと換算します。スケジューラーはサーバーのtickに従うため、サーバーが遅れると両者はずれます。
実行上限
フック、予約コールバック、スクリプトファイルの初期評価には実行上限があります。Lua VMの内部で、実行中に適用します。
| 制限 | 値 |
|---|---|
| 現在のスレッドのCPU時間 | 50ミリ秒 |
| 実行したLua命令数 | 250,000 |
先に到達した上限でLuaエラーを出して呼び出しを中断し、インスタンスを無効にします。
Lua instruction budget exceeded (250000 instruction limit)
Lua CPU-time budget exceeded (50ms current-thread CPU limit)
命令カウンターはwhile true do endのような純粋なLuaループを制限します。時間は1,024命令ごとと呼び出しから戻るときに確認します。実行中のブロッキングJava/Bukkitメソッドを途中で止めることはできません。
CPU時間にはサーバースレッドが実行を割り当てられていなかった時間を含めません。現在のスレッドのCPU時間を取得できないJVMでは、経過時間250ミリ秒を代用します。そのエラーはLua elapsed-time fallback budget exceeded (250ms fallback; current-thread CPU time unavailable)です。250,000命令の上限は維持します。
入れ子の呼び出しは同じ上限を共有します。フックからコールバックを経由して別の関数を呼んでも、全体でCPU時間50msと250,000命令の枠を使います。
プロバイダー検出時の評価は無効な定義を登録前に拒否します。キャッシュ済みソースは、新しいインスタンスごとに同じ上限で再評価します。
- フック内で無制限のループを使わないでください。
- 毎tick動く
on_game_tickは軽い処理にしてください。 context.scheduler:run_repeating(...)で処理を複数tickへ分散してください。
フック一覧
以下は現在動作するプロップのフックです。context.event欄はFMMのキャンセルフラグまたはゾーンのプレイヤーを示します。Luaでは必要に応じてevent.player、event.is_cancelled、event.cancel()、event.uncancel()を提供します。
有効な8つのプロップフック
| フック | 実行条件 | context.event |
|---|---|---|
on_spawn | ワールドに生成されたとき、またはチャンクとともに再び読み込まれたとき | nil |
on_game_tick | 毎サーバーtick。20 TPSなら50ms | nil |
on_destroy | プロップが完全に削除されたとき(チャンクのアンロードやリロードでは呼ばれない) | nil |
on_left_click | プレイヤーの左クリック | 既定ダメージのキャンセルフラグ |
on_right_click | プレイヤーの右クリック | 既定操作のキャンセルフラグ |
on_zone_enter | 監視ゾーンへの入場 | context.player / context.event.player。キャンセル不可 |
on_zone_leave | 監視ゾーンからの退出 | context.player / context.event.player。キャンセル不可 |
on_projectile_hit | 投射物がプロップに当たったとき | 投射物の命中イベント。event.playerは発射者。on_projectile_hitを参照 |
アイテム効果
手持ちアイテムの効果にはカスタムエンチャントを使ってください。旧22種類のアイテムフック表は現在の実行仕様ではありません。
次のステップ
- 例とパターン: 解説と設定手順付きのプロップスクリプト。
- トラブルシューティング: よくある問題、デバッグ、品質確認。
- はじめに: ファイル構成、フック、最初のスクリプト。
EliteMobsの移動ルート
context.world:start_elitemobs_transport(player, route_id)は、コンテキストのワールドに保存したEliteMobsルートをプレイヤーに開始します。戻り値は要求の受付結果です。EliteMobsと読み込み済みのルートが必要で、IDに.ymlを付けません。移動ルートを参照してください。