feat(docs): компонент <Api> переключает JS/Lua инлайны

В уроке 50 (и можно дальше) в тексте было много <code>game.ui.showText</code>,
<code>game.broadcast</code> и т.д. — это JS-API. В Lua-вкладке вики они
оставались JS — путало юзера.

Фикс:
- Новый компонент <Api js="..." lua="..." /> использует useDocsLang().
  Если lang='lua' и lua задан — показывает Lua-эквивалент.
- В уроке 50 заменил все инлайны game.* на <Api> с Lua-параллелями:
  - game.ui.showText → __rbxl_show_text
  - game.sound.play → winSound:Play()
  - game.onMessage/broadcast → BindableEvent:Connect/Fire
  - game.self.onTouch/onInteract/onClick → Touched/UIS+Heartbeat/ClickDetector
  - game.onTick → RunService.Heartbeat
  - game.after/every → task.delay/spawn
  - game.tween → TweenService:Create
  - game.scene.spawnNpc → __rbxl_spawn_npc
  - game.ui.score → __rbxl_score_set
This commit is contained in:
min 2026-06-09 23:29:41 +03:00
parent ddeb8ff93f
commit 61026a1df0

View File

@ -1,6 +1,6 @@
import React from 'react';
import { Code, ScriptKind, Step, Note, Try, Shot } from './docsData';
import { LangTabs } from './docsLang';
import { LangTabs, useDocsLang } from './docsLang';
import { LUA_OVERRIDES } from './docsGamesBuildersLua';
/**
@ -20,6 +20,17 @@ function CodeBoth({ game, script, children }) {
);
}
/**
* Инлайн-API-имена в тексте уроков, меняющиеся в зависимости от JS/Lua вкладки.
* <Api js="game.ui.showText('Победа!', 5)" lua={'__rbxl_show_text("Победа!", 5)'} />
* Если lua не задан показывает js в обоих режимах.
*/
function Api({ js, lua }) {
const { lang } = useDocsLang();
const txt = lang === 'lua' && lua ? lua : js;
return <code>{txt}</code>;
}
/**
* docsLessons.jsx тексты уроков для 50 мини-игр (раздел K вики).
*
@ -7270,8 +7281,10 @@ game.self.onTouch(() => {
</ul>
<p>
И обязательно покажи игроку, когда он <b>победил</b>
надписью <code>game.ui.showText('Победа!', 5)</code>,
звуком <code>game.sound.play('win')</code> и конфетти.
надписью <Api js="game.ui.showText('Победа!', 5)"
lua={'__rbxl_show_text("Победа!", 5)'} />,
звуком <Api js="game.sound.play('win')"
lua={'winSound:Play()'} /> и конфетти.
</p>
<h3 className="lessonH">Шаг 4. Напиши скрипты</h3>
@ -7279,34 +7292,48 @@ game.self.onTouch(() => {
Сцена сама по себе не «живая» её оживляют скрипты.
Начинай с <b>главного скрипта</b>: в нём заводи переменные
(счёт, флажок победы) и <b>лови сообщения</b> через
<code> game.onMessage('имя', fn)</code>. На объекты вешай
небольшие скрипты они шлют сообщения главному через
<code> game.broadcast('имя')</code>. Так главный скрипт
узнаёт, что монетку собрали или кнопку нажали. Ты делал
так в каждом уроке.
<> </><Api js="game.onMessage('имя', fn)"
lua={'getEvent("Имя").Event:Connect(fn)'} />.
На объекты вешай небольшие скрипты они шлют сообщения
главному через <Api js="game.broadcast('имя')"
lua={'getEvent("Имя"):Fire()'} />.
Так главный скрипт узнаёт, что монетку собрали или кнопку
нажали. Ты делал так в каждом уроке.
</p>
<Note>
Каждый скрипт работает в своей «песочнице» переменные
одного скрипта не видны другому. Поэтому скрипты общаются
сообщениями: один шлёт <code>game.broadcast('имя')</code>,
другой ловит <code>game.onMessage('имя', fn)</code>. Можно
передать данные: <code>game.broadcast('имя', {'{'} ... {'}'})</code>.
сообщениями: один шлёт <Api js="game.broadcast('имя')"
lua={'getEvent("Имя"):Fire()'} />,
другой ловит <Api js="game.onMessage('имя', fn)"
lua={'getEvent("Имя").Event:Connect(fn)'} />.
Можно передать данные: <Api
js="game.broadcast('имя', { ... })"
lua={'getEvent("Имя"):Fire(data)'} />.
</Note>
<p>Базовый набор инструментов, который ты знаешь:</p>
<ul>
<li><code>game.self.onTouch</code> реакция на касание;</li>
<li><code>game.self.onInteract</code> реакция на
<li><Api js="game.self.onTouch"
lua={'part.Touched:Connect(fn)'} /> реакция на касание;</li>
<li><Api js="game.self.onInteract"
lua={'UserInputService.InputBegan + Heartbeat (дистанция)'} /> реакция на
<kbd className="kbd">E</kbd>;</li>
<li><code>game.self.onClick</code> реакция на клик;</li>
<li><code>game.broadcast</code> и <code>game.onMessage</code>
<li><Api js="game.self.onClick"
lua={'ClickDetector + MouseClick:Connect'} /> реакция на клик;</li>
<li><Api js="game.broadcast" lua={'BindableEvent:Fire'} /> и
<> </><Api js="game.onMessage" lua={'BindableEvent.Event:Connect'} />
связь между скриптами;</li>
<li><code>game.onTick</code> каждый кадр;</li>
<li><code>game.after</code> и <code>game.every</code>
таймеры;</li>
<li><code>game.tween</code> плавное движение;</li>
<li><code>game.scene.spawnNpc</code> враги и NPC;</li>
<li><code>game.ui.score</code> и
<code> game.ui.showText</code> счёт и подсказки.</li>
<li><Api js="game.onTick"
lua={'RunService.Heartbeat:Connect'} /> каждый кадр;</li>
<li><Api js="game.after / game.every"
lua={'task.delay / task.spawn'} /> таймеры;</li>
<li><Api js="game.tween"
lua={'TweenService:Create(part, TweenInfo.new(t), goal):Play()'} /> плавное движение;</li>
<li><Api js="game.scene.spawnNpc"
lua={'__rbxl_spawn_npc("character-b", x, y, z, name, hp, speed)'} /> враги и NPC;</li>
<li><Api js="game.ui.score" lua={'__rbxl_score_set(N)'} /> и
<> </><Api js="game.ui.showText"
lua={'__rbxl_show_text(text, duration)'} /> счёт и подсказки.</li>
</ul>
<h3 className="lessonH">Шаг 5. Проверяй и улучшай</h3>