// Create RP — туторіал у стилі Create (Ponder): наведи на предмет і затисни W. // Потрібні PonderJS (мод «Ponder for KubeJS») і startup_scripts/createrp_items.js (предмет kubejs:citizen_guide). // Більшість сцен — на стандартній плиті 5x5 (y=0 — плита, блоки з y=1); продаж і покупки — на схематиці Create з ланцюгами. Текст: _слово_ — підсвітка, як у Create. const PACKAGE = 'create:cardboard_package_10x12' // Справжні посилки на ланцюгах — тими ж викликами, що й у сценах самого Create (FrogAndConveyorScenes). // Якщо KubeJS не дасть доступу до класів — сцени все одно покажуть мережу й текст, лише без руху посилок. let CreateScene = null, Frogport = null, ChainConveyor = null, PackageItem = null, PackageStyles = null try { CreateScene = Java.loadClass('com.simibubi.create.foundation.ponder.CreateSceneBuilder') Frogport = Java.loadClass('com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlockEntity') ChainConveyor = Java.loadClass('com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity') PackageItem = Java.loadClass('com.simibubi.create.content.logistics.box.PackageItem') PackageStyles = Java.loadClass('com.simibubi.create.content.logistics.box.PackageStyles') } catch (e) { console.warn('[createrp] Create classes unavailable for Ponder animations: ' + e) } // посилка з адресою їде ланцюгами від пакужаби from до пакужаби to (по вузлах CONV2 → CONV1) function shipOnChains(scene, util, address) { if (!Frogport) { scene.overlay.showBigLine(PonderPalette.OUTPUT, [5.5, 3, 2.5], [2.5, 3, 5.5], 140) scene.idle(150) return } const box = addressedBox(address) scene.world.modifyBlockEntity(util.grid.at(FROM_FROG[0], FROM_FROG[1], FROM_FROG[2]), Frogport, be => be.startAnimation(box, true)) scene.idle(95) chainTransfer(scene, util, CONV1, CONV2) scene.idle(45) frogTakes(scene, util, CONV1, TO_FROG, box) scene.idle(10) } function setSpeed(scene, util, sel, speed) { if (CreateScene) new CreateScene(scene).world().setKineticSpeed(sel, speed) } // схематика Create «Transporting packages between Frogports» (9x9): ланцюги на висоті 4, дві пакужаби const FROG_STRUCTURE = 'create:high_logistics/package_frogport' const CONV1 = [1, 4, 7], CONV2 = [7, 4, 7] const FROM_FROG = [5, 2, 2], TO_FROG = [2, 2, 5] function addressedBox(address) { const box = PackageStyles.getDefaultBox().copy() PackageItem.addAddress(box, address) return box } // посилки, що крутяться на одному ланцюговому вузлі, їдуть до іншого (Create: boxTransfer) function chainTransfer(scene, util, to, from) { scene.world.modifyBlockEntity(util.grid.at(from[0], from[1], from[2]), ChainConveyor, be => { const it = be.getLoopingPackages().iterator() while (it.hasNext()) { const p = it.next() p.chainPosition = 0 be.addTravellingPackage(p, util.grid.at(to[0] - from[0], to[1] - from[1], to[2] - from[2])) it.remove() } }) } // пакужаба на прийомі: знімає посилки з вузла й «ковтає» їх function frogTakes(scene, util, conv, frog, box) { scene.world.modifyBlockEntity(util.grid.at(conv[0], conv[1], conv[2]), ChainConveyor, be => be.getLoopingPackages().clear()) scene.world.modifyBlockEntity(util.grid.at(frog[0], frog[1], frog[2]), Frogport, be => be.startAnimation(box, false)) } // спільна частина: мережа ланцюгів з'являється так само, як у Create function showChainNetwork(scene, util) { scene.configureBasePlate(0, 0, 9) scene.scaleSceneView(0.75) scene.setSceneOffsetY(-1) scene.world.showSection(util.select.layer(0).substract(util.select.position(9, 0, 1)), Direction.UP) scene.idle(10) scene.world.showSection(util.select.position(2, 1, 8), Direction.SOUTH) scene.idle(2) scene.world.showSection(util.select.fromTo(1, 1, 7, 1, 3, 7), Direction.DOWN) scene.idle(2) scene.world.showSection(util.select.fromTo(7, 1, 7, 7, 3, 7), Direction.DOWN) scene.idle(2) scene.world.showSection(util.select.fromTo(7, 1, 1, 7, 3, 1), Direction.DOWN) scene.idle(5) scene.world.showSection(util.select.position(1, 4, 7), Direction.DOWN) scene.world.showSection(util.select.position(7, 4, 7), Direction.DOWN) scene.world.showSection(util.select.position(7, 4, 1), Direction.DOWN) scene.idle(20) } // --------------------------------------------------------------------------------------------- // 1. Термінал держави function terminalScene(scene, util) { scene.showBasePlate() scene.world.setBlocks([2, 1, 2], 'computercraft:computer_advanced') scene.world.setBlocks([1, 1, 3, 3, 2, 3], 'computercraft:monitor_advanced') scene.idle(10) scene.world.showSection([2, 1, 2], Direction.DOWN) scene.idle(15) scene.text(80, 'Будь-який _комп\'ютер_ — це термінал держави. Відкрий його й набери _rp_.', [2.5, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.showControls(60, [2.5, 2, 2.5], 'down').rightClick() scene.idle(90) scene.text(90, 'Вхід — твій _нік_ і _пароль_. Першого разу термінал попросить створити пароль. Стій поруч із комп\'ютером — здалеку не пустить.', [2.5, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(100) scene.text(90, 'У меню: _рахунок_, _бізнес_, _ціни_, _магазин_, _земля_, _робота_, _тендери_, _банк_. Стрілки й Enter, Backspace — назад.', [2.5, 1.5, 2.5]) .placeNearTarget() scene.idle(100) scene.world.showSection([1, 1, 3, 3, 2, 3], Direction.DOWN) scene.idle(15) scene.text(90, 'Комп\'ютер з _монітором_ — табло цін держави: програма _prices metal_ (або stone, wood, farm, food, create…).', [2, 2.5, 3]) .colored(PonderPalette.BLUE).placeNearTarget().attachKeyFrame() scene.idle(100) } // --------------------------------------------------------------------------------------------- // 2. Продаж державі (схематика Create з ланцюгами) function sellScene(scene, util) { showChainNetwork(scene, util) scene.text(90, 'Бізнеси й держава з\'єднані _мережею ланцюгів_. Посилка сама знаходить пакужабу з потрібною адресою.', [4, 4.5, 7]) .placeNearTarget().attachKeyFrame() scene.idle(100) // бізнес: сховище, пакувальник з табличкою, пакужаба на ланцюгу scene.world.showSection(util.select.fromTo(7, 1, 2, 5, 1, 2), Direction.DOWN) scene.world.showSection(util.select.position(5, 1, 3), Direction.DOWN) scene.idle(5) scene.world.showSection(util.select.position(4, 1, 2), Direction.EAST) scene.world.showSection(util.select.position(5, 2, 2), Direction.DOWN) scene.idle(15) scene.text(110, 'Твій бізнес: сховище → _пакувальник_ → _пакужаба_ на ланцюгу. Табличка на пакувальнику — адреса продажу _gov-…_ (термінал → Бізнес → Адреса продажу).', [4.5, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(120) // держава: пакужаба з фільтром gov-* і приймач під нею scene.world.showSection(util.select.position(2, 1, 5), Direction.SOUTH) scene.world.showSection(util.select.fromTo(2, 1, 4, 0, 1, 4), Direction.DOWN) scene.idle(5) scene.world.showSection(util.select.position(2, 2, 5), Direction.DOWN) scene.idle(15) scene.text(100, '_Державна пакужаба_ приймає посилки на всі адреси gov-… Під нею — державний приймач.', [2.5, 2.5, 5.5]) .colored(PonderPalette.BLUE).placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(70, 'Посилка з адресою gov-… їде ланцюгами…', [6.78, 4.37, 3.5]).placeNearTarget() shipOnChains(scene, util, 'gov-a1b2c3') scene.text(110, '…до держави. Гроші — на _рахунок бізнесу_. Товару забагато — ціна падає, дефіцит — росте. Ціни — на табло й у терміналі.', [2.5, 2.5, 5.5]) .colored(PonderPalette.GREEN).placeNearTarget().attachKeyFrame() scene.idle(120) scene.text(80, 'Поїзди, ферми, ланцюги — продаж іде сам, поки ти робиш інше.', [4, 4.5, 4]) scene.idle(90) } // --------------------------------------------------------------------------------------------- // 3. Покупка в держави (та сама мережа, напрямок навпаки) function buyScene(scene, util) { showChainNetwork(scene, util) scene.world.showSection(util.select.fromTo(7, 1, 2, 5, 1, 2), Direction.DOWN) scene.world.showSection(util.select.position(5, 1, 3), Direction.DOWN) scene.idle(5) scene.world.showSection(util.select.position(5, 2, 2), Direction.DOWN) scene.idle(15) scene.text(100, '_Державний склад_: пакувальник і пакужаба держави на тій самій мережі ланцюгів.', [5.5, 2.5, 2.5]) .colored(PonderPalette.BLUE).placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(100, 'Держава продає _імпорт_ (алмази, незерит, елітри…) і _ліцензії_. Купівля — термінал → Магазин держави.', [4, 4.5, 4]) .placeNearTarget().attachKeyFrame() scene.idle(110) scene.world.showSection(util.select.position(2, 1, 5), Direction.SOUTH) scene.world.showSection(util.select.fromTo(2, 1, 4, 0, 1, 4), Direction.DOWN) scene.world.showSection(util.select.position(3, 1, 5), Direction.DOWN) scene.idle(5) scene.world.showSection(util.select.position(2, 2, 5), Direction.DOWN) scene.idle(15) scene.text(100, 'Твоя пакужаба з адресою, напр. _Склад Олі_. Цю назву вкажи під час покупки — термінал запам\'ятає.', [2.5, 2.5, 5.5]) .placeNearTarget().attachKeyFrame() scene.idle(110) shipOnChains(scene, util, 'Склад Олі') scene.text(100, 'Посилка приходить сама. _Пакувальник_ під твоєю пакужабою розпакує її у скриню.', [3.5, 1.5, 5.5]) .colored(PonderPalette.GREEN).placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(80, 'Не дійшла? Гроші _повертаються_ автоматично, а в чаті буде причина.', [4, 4.5, 4]) scene.idle(90) } // --------------------------------------------------------------------------------------------- // 7. Продаж енергії державі function energyScene(scene, util) { scene.showBasePlate() scene.world.setBlocks([0, 1, 2], 'create:water_wheel[facing=east]') scene.world.setBlocks([1, 1, 2], 'create:shaft[axis=x]') scene.world.setBlocks([2, 1, 2], 'create:stressometer[facing=south,axis_along_first=true]') scene.world.setBlocks([3, 1, 2], 'create:shaft[axis=x]') scene.world.setBlocks([4, 1, 2], 'create:encased_fan[facing=east]') scene.idle(10) scene.world.showSection([0, 1, 2], Direction.DOWN) scene.world.showSection([1, 1, 2], Direction.DOWN) scene.idle(10) setSpeed(scene, util, util.select.fromTo(0, 1, 2, 1, 1, 2), 16) scene.text(90, 'Енергію теж можна _продавати державі_. Твій генератор — колесо, вітряк, двигун — крутить вал до державної мережі.', [0.5, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(100) scene.world.showSection([3, 1, 2, 4, 1, 2], Direction.DOWN) scene.idle(10) scene.world.showSection([2, 1, 2], Direction.DOWN) scene.idle(10) setSpeed(scene, util, util.select.fromTo(0, 1, 2, 4, 1, 2), 16) scene.overlay.showOutline(PonderPalette.GREEN, 'biz', util.select.fromTo(0, 1, 2, 1, 1, 2), 100) scene.overlay.showOutline(PonderPalette.BLUE, 'state', util.select.fromTo(3, 1, 2, 4, 1, 2), 100) scene.text(100, 'На стику — _державний лічильник_ (стресометр). Його ставить держава і прив\'язує до твого бізнесу.', [2.5, 1.8, 2.5]) .colored(PonderPalette.BLUE).placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(110, 'Щохвилини держава платить бізнесу за _силу_ (SU), яку забирають її машини, — до ліміту лічильника.', [3.5, 1.5, 2.5]) .colored(PonderPalette.GREEN).placeNearTarget().attachKeyFrame() scene.idle(120) setSpeed(scene, util, util.select.fromTo(0, 1, 2, 4, 1, 2), 0) scene.text(90, 'Генератор зупинився — оплата зупинилась. Перевантажив мережу — теж нічого не заробиш.', [1.5, 1.5, 2.5]) .colored(PonderPalette.RED).placeNearTarget() scene.idle(100) setSpeed(scene, util, util.select.fromTo(0, 1, 2, 4, 1, 2), 16) scene.text(80, 'Хочеш лічильник? Звернися до держави — вона підключить твою електростанцію.', [2.5, 2.5, 2.5]) scene.idle(90) } // --------------------------------------------------------------------------------------------- // 4. Гроші й банк function moneyScene(scene, util) { scene.showBasePlate() scene.world.setBlocks([2, 1, 2], 'computercraft:computer_advanced') scene.world.showSection([2, 1, 2], Direction.DOWN) scene.idle(15) scene.text(90, 'Твої гроші — на _рахунку_ в державному банку. Баланс і перекази — термінал → Рахунок.', [2.5, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(100) const coins = ['numismatics:spur', 'numismatics:bevel', 'numismatics:sprocket', 'numismatics:cog'] for (let i = 0; i < coins.length; i++) { scene.world.createItemEntity([1 + i, 3, 1], [0, 0.1, 0], coins[i]) scene.idle(5) } scene.idle(10) scene.text(110, '_Готівка_ — монети: зняти /cash withdraw <сума>, покласти — /cash deposit з монетами в руці. Готівкою платять одне одному з рук.', [2.5, 2, 1.5]) .colored(PonderPalette.GREEN).placeNearTarget().attachKeyFrame() scene.idle(120) scene.text(100, '_Банк_ (термінал → Банк): стартовий та інвестиційний кредити для бізнесу, вклади під відсоток щодня.', [2.5, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(90, 'Кредит платиться щоденними внесками. Пропустиш тричі — _дефолт_: рахунок бізнесу заморожено, тендери заборонені.', [2.5, 1.5, 2.5]) .colored(PonderPalette.RED).placeNearTarget() scene.idle(100) } // --------------------------------------------------------------------------------------------- // 5. Земля й надра function landScene(scene, util) { scene.showBasePlate() scene.world.setBlocks([1, 1, 1], 'minecraft:oak_fence') scene.world.setBlocks([3, 1, 1], 'minecraft:oak_fence') scene.world.setBlocks([1, 1, 3], 'minecraft:oak_fence') scene.world.setBlocks([3, 1, 3], 'minecraft:oak_fence') scene.world.setBlocks([2, 1, 2], 'minecraft:iron_ore') scene.idle(10) scene.text(90, 'Уся незареєстрована земля _належить державі_. Будувати можна на своїх ділянках.', [2.5, 1, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(100) scene.overlay.showOutline(PonderPalette.GREEN, 'plot', util.select.fromTo(0, 0, 0, 4, 0, 4), 120) scene.world.showSection([1, 1, 1, 3, 1, 3], Direction.DOWN) scene.text(110, '_Ділянки_ орендують на ігрові дні або викуповують: термінал → Земля. Заходячи на ділянку, бачиш її назву над хотбаром.', [2.5, 1.5, 2.5]) .colored(PonderPalette.GREEN).placeNearTarget().attachKeyFrame() scene.idle(120) scene.text(100, 'Орендована ділянка — _приват_ бізнесу: чужі не ламають, а твої працівники мають доступ.', [2.5, 1.5, 2.5]) .placeNearTarget() scene.idle(110) scene.overlay.showOutline(PonderPalette.RED, 'ore', util.select.position(2, 1, 2), 100) scene.text(100, '_Руда_ видобувається за _концесією_: купи дозвіл на руду й квоту на ділянці (термінал → Земля → Купити концесію).', [2.5, 1.5, 2.5]) .colored(PonderPalette.RED).placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(80, 'За землю щодня — орендна плата або податок. Не заплатив 3 дні — ділянка повертається державі.', [2.5, 2.5, 2.5]) scene.idle(90) } // --------------------------------------------------------------------------------------------- // 6. Робота: ринок праці і пошта function jobsScene(scene, util) { scene.showBasePlate() scene.idle(10) const post = scene.world.createEntity('minecraft:villager', [1, 1, 2.5]) scene.idle(10) scene.text(90, 'Немає роботи? Термінал → Робота → _ринок праці_: допомога по безробіттю щодня, якщо ти був активний у грі.', [2.5, 2.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(100) scene.text(90, 'Хочеш заробляти більше — стань _поштарем_. Клікни по NPC пошти.', [1, 2.5, 2.5]) .colored(PonderPalette.BLUE).placeNearTarget().attachKeyFrame() scene.showControls(60, [1, 2.3, 2.5], 'down').rightClick() scene.idle(70) scene.world.createItemEntity([1.5, 2, 2.5], [0.05, 0.25, 0], PACKAGE) scene.world.createItemEntity([1.5, 2, 2.5], [0.03, 0.3, 0.03], 'minecraft:compass') scene.idle(20) scene.text(100, 'Отримаєш _посилку_ з іменем адресата й _компас_, що вказує на нього. ПКМ компасом — мітка на місці (видно лише тобі).', [2, 1.5, 2.5]) .placeNearTarget().attachKeyFrame() scene.idle(110) scene.world.createEntity('minecraft:villager', [4, 1, 2.5]) scene.overlay.showBigLine(PonderPalette.OUTPUT, [1.5, 1.2, 2.5], [4, 1.2, 2.5], 80) scene.text(100, 'Адресат чекає в іншій частині світу. Принеси посилку й клікни по ньому — гроші на рахунок. Що далі, то дорожче.', [4, 2.5, 2.5]) .colored(PonderPalette.GREEN).placeNearTarget().attachKeyFrame() scene.idle(110) scene.text(80, 'На доставку — _2 ігрові дні_. Не встиг — адресат поїде, і посилка згорить.', [2.5, 2.5, 2.5]) .colored(PonderPalette.RED) scene.idle(90) scene.text(90, 'Або наймися до бізнесу: власник пропонує зарплату, ти приймаєш у терміналі → Бізнес → Прийняти запрошення.', [2.5, 2.5, 2.5]) scene.idle(100) } // --------------------------------------------------------------------------------------------- Ponder.tags(event => { event.createTag('kubejs:createrp', 'kubejs:citizen_guide', 'Держава Create RP', 'Як жити й заробляти в державній економіці: термінал, продаж і покупки посилками, енергія, гроші, земля, робота.', ['kubejs:citizen_guide', 'create:package_frogport', 'computercraft:computer_advanced', 'computercraft:computer_normal', 'computercraft:monitor_advanced', 'create:stressometer']) }) Ponder.registry(event => { event.create('kubejs:citizen_guide') .scene('guide_terminal', 'Термінал держави', terminalScene) .scene('guide_sell', 'Продаж державі', FROG_STRUCTURE, sellScene) .scene('guide_buy', 'Покупки в держави', FROG_STRUCTURE, buyScene) .scene('guide_energy', 'Продаж енергії державі', energyScene) .scene('guide_money', 'Гроші й банк', moneyScene) .scene('guide_land', 'Земля й надра', landScene) .scene('guide_jobs', 'Робота: ринок праці й пошта', jobsScene) event.create('create:package_frogport') .scene('frogport_sell', 'Create RP: продаж державі', FROG_STRUCTURE, sellScene) .scene('frogport_buy', 'Create RP: покупки в держави', FROG_STRUCTURE, buyScene) event.create('create:stressometer') .scene('stressometer_energy', 'Create RP: продаж енергії державі', energyScene) event.create(['computercraft:computer_advanced', 'computercraft:computer_normal']) .scene('computer_terminal', 'Create RP: термінал держави', terminalScene) event.create('computercraft:monitor_advanced') .scene('monitor_terminal', 'Create RP: термінал і табло цін', terminalScene) })