@nice2dev/game-engine 1.3.15 → 1.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/cjs/accessibility/Accessibility.js +152 -165
- package/dist/cjs/ai/AI.js +292 -294
- package/dist/cjs/ai/BehaviorTree.js +1029 -1113
- package/dist/cjs/ai/StateMachine.js +694 -756
- package/dist/cjs/animation/Animation.js +232 -241
- package/dist/cjs/audio/AudioAdvanced.js +221 -236
- package/dist/cjs/audio/AudioBridge.js +441 -435
- package/dist/cjs/audio/AudioManager.js +242 -259
- package/dist/cjs/build-cloud/BuildOrchestration.js +1059 -1098
- package/dist/cjs/build-cloud/GodotBuildCloud.js +641 -670
- package/dist/cjs/build-cloud/UnityBuildCloud.js +563 -610
- package/dist/cjs/build-cloud/UnrealBuildCloud.js +610 -635
- package/dist/cjs/core/EventBus.js +51 -56
- package/dist/cjs/core/GameClock.js +62 -66
- package/dist/cjs/core/GameConfig.js +72 -79
- package/dist/cjs/core/GameLoop.js +80 -89
- package/dist/cjs/core/ServiceLocator.js +61 -65
- package/dist/cjs/core/Validation.js +72 -82
- package/dist/cjs/core/math.js +108 -112
- package/dist/cjs/devtools/DevTools.js +542 -563
- package/dist/cjs/devtools/DeveloperExperience.js +521 -559
- package/dist/cjs/devtools/GameplayAnalytics.js +636 -646
- package/dist/cjs/dialogue/DialogueSystem.js +984 -986
- package/dist/cjs/docs/DocGenerator.js +339 -364
- package/dist/cjs/ecs/World.js +355 -371
- package/dist/cjs/editor/AchievementEditor.js +580 -636
- package/dist/cjs/editor/AdvancedEditor.js +184 -191
- package/dist/cjs/editor/AnimationRetargeting.js +696 -741
- package/dist/cjs/editor/AssetBrowser.js +1072 -1160
- package/dist/cjs/editor/AssetManager.js +187 -192
- package/dist/cjs/editor/ConsolePro.js +971 -1061
- package/dist/cjs/editor/CraftingEditor.js +680 -730
- package/dist/cjs/editor/DebugTools.js +187 -185
- package/dist/cjs/editor/DialogueSystem.js +844 -901
- package/dist/cjs/editor/LeaderboardSystem.js +429 -483
- package/dist/cjs/editor/NiceGameEditor.js +1903 -1201
- package/dist/cjs/editor/PrefabSystem.js +772 -838
- package/dist/cjs/editor/ProfilerPanel.js +649 -700
- package/dist/cjs/editor/QuestEditor.js +792 -839
- package/dist/cjs/editor/ReplaySystem.js +585 -634
- package/dist/cjs/editor/SceneEditor.js +176 -200
- package/dist/cjs/editor/ScreenshotMode.js +621 -688
- package/dist/cjs/editor/ShaderGraph.js +1556 -1582
- package/dist/cjs/editor/TimelineEditor.js +715 -778
- package/dist/cjs/editor/UndoRedoPro.js +830 -904
- package/dist/cjs/editor/VRARMode.js +582 -645
- package/dist/cjs/engine/NiceGameEngine.js +141 -164
- package/dist/cjs/engine/SaveSystem.js +441 -495
- package/dist/cjs/enterprise/Enterprise.js +254 -261
- package/dist/cjs/export/BevyExporter.js +927 -967
- package/dist/cjs/export/CocosExporter.js +644 -673
- package/dist/cjs/export/Construct3Exporter.js +783 -794
- package/dist/cjs/export/DefoldExporter.js +1028 -1069
- package/dist/cjs/export/GDevelopExporter.js +674 -708
- package/dist/cjs/export/GameMakerExporter.js +791 -805
- package/dist/cjs/export/GodotExporter.js +1003 -1045
- package/dist/cjs/export/MinecraftBedrockExporter.js +573 -578
- package/dist/cjs/export/MonoGameExporter.js +1265 -1293
- package/dist/cjs/export/Pico8Exporter.js +766 -812
- package/dist/cjs/export/PlatformExporter.js +188 -206
- package/dist/cjs/export/RPGMakerExporter.js +860 -879
- package/dist/cjs/export/RobloxExporter.js +883 -919
- package/dist/cjs/export/Solar2DExporter.js +1218 -1256
- package/dist/cjs/export/ThreeJSExporter.js +1006 -1073
- package/dist/cjs/export/Tic80Exporter.js +1210 -1267
- package/dist/cjs/export/UnityExporter.js +1116 -1131
- package/dist/cjs/export/UnrealExporter.js +889 -919
- package/dist/cjs/export/WebExporter.js +931 -970
- package/dist/cjs/export/index.js +42 -65
- package/dist/cjs/godot-integration/GodotAssetLibrary.js +659 -692
- package/dist/cjs/godot-integration/GodotImport.js +929 -1027
- package/dist/cjs/godot-integration/GodotLiveLink.js +915 -945
- package/dist/cjs/godot-integration/components/GodotProjectBrowser.js +911 -611
- package/dist/cjs/i18n/I18n.js +860 -900
- package/dist/cjs/i18n/useTranslation.js +84 -89
- package/dist/cjs/import/AsepriteImporter.js +658 -716
- package/dist/cjs/import/DragonBonesImporter.js +437 -461
- package/dist/cjs/import/GameMakerImporter.js +511 -521
- package/dist/cjs/import/GodotSceneImporter.js +788 -822
- package/dist/cjs/import/LDtkImporter.js +436 -454
- package/dist/cjs/import/Live2DImporter.js +497 -518
- package/dist/cjs/import/NdgFormat.js +424 -457
- package/dist/cjs/import/OgmoImporter.js +466 -493
- package/dist/cjs/import/RPGMakerImporter.js +451 -477
- package/dist/cjs/import/SceneImporter.js +378 -423
- package/dist/cjs/import/SpineImporter.js +511 -546
- package/dist/cjs/import/SpriterImporter.js +590 -613
- package/dist/cjs/import/TiledMapImporter.js +811 -846
- package/dist/cjs/import/UnitySceneImporter.js +687 -703
- package/dist/cjs/import/index.js +206 -251
- package/dist/cjs/index.js +275 -278
- package/dist/cjs/input/GamepadNavigation.js +185 -205
- package/dist/cjs/input/InputManager.js +397 -421
- package/dist/cjs/input/useGamepads.js +70 -81
- package/dist/cjs/integration/IconSprite.js +129 -256
- package/dist/cjs/inventory/InventorySystem.js +920 -995
- package/dist/cjs/kids/KidMode.js +997 -1022
- package/dist/cjs/kids/KidTools.js +570 -594
- package/dist/cjs/monetization/Monetization.js +170 -177
- package/dist/cjs/multiplayer/LocalMultiplayer.js +287 -287
- package/dist/cjs/multiplayer/MiniGameTypes.js +49 -59
- package/dist/cjs/native-engine/AnimationSystem.js +731 -806
- package/dist/cjs/native-engine/AssetPipeline.js +454 -515
- package/dist/cjs/native-engine/AudioEngine.js +763 -804
- package/dist/cjs/native-engine/InputSystem.js +1075 -1145
- package/dist/cjs/native-engine/NetworkingSystem.js +733 -793
- package/dist/cjs/native-engine/PhysicsEngine.js +583 -607
- package/dist/cjs/native-engine/RenderingEngine.js +302 -350
- package/dist/cjs/native-engine/SceneGraph.js +769 -808
- package/dist/cjs/network/MultiplayerTransport.js +97 -132
- package/dist/cjs/network/Networking.js +549 -564
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AbortController.js +21 -29
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js +40 -48
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js +35 -43
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js +10 -15
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Errors.js +103 -135
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js +131 -158
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js +39 -53
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js +5 -8
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpClient.js +40 -48
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js +494 -572
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnection.js +826 -953
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js +125 -146
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js +13 -23
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ILogger.js +11 -25
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ITransport.js +13 -24
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js +108 -121
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Loggers.js +10 -14
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js +150 -185
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js +158 -196
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js +90 -105
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Subject.js +30 -35
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js +16 -21
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Utils.js +215 -248
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js +135 -157
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js +76 -85
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/index.js +24 -27
- package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/pkg-version.js +3 -4
- package/dist/cjs/pathfinding/Pathfinding.js +245 -263
- package/dist/cjs/performance/AssetStreaming.js +561 -635
- package/dist/cjs/performance/BenchmarkSuite.js +283 -311
- package/dist/cjs/performance/DeltaCompression.js +467 -526
- package/dist/cjs/performance/DeterministicPhysics.js +450 -498
- package/dist/cjs/performance/ECSOptimization.js +644 -695
- package/dist/cjs/performance/GameSaveSystem.js +509 -556
- package/dist/cjs/performance/HotReload.js +447 -500
- package/dist/cjs/performance/InputRecording.js +511 -561
- package/dist/cjs/performance/InterestManagement.js +453 -500
- package/dist/cjs/performance/LocalizationRuntime.js +376 -423
- package/dist/cjs/performance/MemoryManagement.js +410 -470
- package/dist/cjs/performance/ModSupport.js +445 -496
- package/dist/cjs/performance/MultiThreadedPhysics.js +400 -443
- package/dist/cjs/performance/NetworkPrediction.js +424 -482
- package/dist/cjs/performance/ObjectPooling.js +569 -617
- package/dist/cjs/performance/Performance.js +174 -190
- package/dist/cjs/performance/PerformanceAdvanced.js +614 -637
- package/dist/cjs/performance/WebGPURenderer.js +656 -683
- package/dist/cjs/physics/PhysicsAdvanced.js +345 -379
- package/dist/cjs/physics/PhysicsEngine2D.js +391 -427
- package/dist/cjs/plugins/PluginSDK.js +432 -466
- package/dist/cjs/plugins/PluginTestKit.js +307 -330
- package/dist/cjs/procedural/Procedural.js +243 -254
- package/dist/cjs/procedural/WorldBuilding.js +297 -314
- package/dist/cjs/quest/QuestSystem.js +975 -932
- package/dist/cjs/release/MobileExport.js +157 -163
- package/dist/cjs/release/Release.js +225 -238
- package/dist/cjs/rendering/Camera2D.js +121 -124
- package/dist/cjs/rendering/Renderer2D.js +321 -335
- package/dist/cjs/rendering/WebGPURenderPipeline.js +632 -651
- package/dist/cjs/runtime3d/Runtime3D.js +359 -378
- package/dist/cjs/runtime3d/SceneEditor3D.js +252 -263
- package/dist/cjs/scene/SceneManager.js +177 -193
- package/dist/cjs/scripting/GraphToAST.js +574 -547
- package/dist/cjs/scripting/LanguageExporter.js +254 -279
- package/dist/cjs/scripting/NodeGraph.js +546 -570
- package/dist/cjs/scripting/ScriptAST.js +31 -39
- package/dist/cjs/scripting/VisualScripting2.js +1016 -1065
- package/dist/cjs/scripting/exporters/CSharpExporter.js +464 -496
- package/dist/cjs/scripting/exporters/GDScriptExporter.js +390 -442
- package/dist/cjs/scripting/exporters/LuaExporter.js +406 -447
- package/dist/cjs/scripting/exporters/PythonExporter.js +484 -549
- package/dist/cjs/scripting/exporters/RustExporter.js +459 -512
- package/dist/cjs/scripting/exporters/TypeScriptExporter.js +505 -556
- package/dist/cjs/social/Social.js +72 -80
- package/dist/cjs/systems/LightingSystem.js +844 -931
- package/dist/cjs/systems/ParticleSystem2.js +1447 -1451
- package/dist/cjs/systems/PhysicsDebugSystem.js +1070 -1141
- package/dist/cjs/systems/TerrainSystem.js +985 -1098
- package/dist/cjs/templates/ActionTemplates.js +296 -309
- package/dist/cjs/templates/FightingTemplate.js +417 -463
- package/dist/cjs/templates/MetroidvaniaTemplate.js +353 -405
- package/dist/cjs/templates/PartyTemplates.js +190 -202
- package/dist/cjs/templates/PuzzleTemplates.js +245 -261
- package/dist/cjs/templates/RPGTemplates.js +160 -178
- package/dist/cjs/templates/SportsTemplates.js +237 -250
- package/dist/cjs/templates/StrategyTemplates.js +143 -153
- package/dist/cjs/templates/SurvivalTemplate.js +336 -380
- package/dist/cjs/templates/WaveDefense.js +499 -526
- package/dist/cjs/tilemap/Tilemap.js +207 -214
- package/dist/cjs/tutorials/TutorialBranching.js +396 -417
- package/dist/cjs/tutorials/TutorialEngine.js +888 -931
- package/dist/cjs/tutorials/TutorialOverlay.js +602 -640
- package/dist/cjs/tutorials/content/Tutorials_T05_T08.js +787 -809
- package/dist/cjs/tutorials/content/Tutorials_T09_T11.js +736 -756
- package/dist/cjs/tutorials/content/Tutorials_T12_T15.js +754 -778
- package/dist/cjs/ui/GameUI.js +295 -312
- package/dist/cjs/unity-integration/UnityAssetStore.js +700 -741
- package/dist/cjs/unity-integration/UnityImport.js +1066 -1176
- package/dist/cjs/unity-integration/UnityLiveLink.js +934 -981
- package/dist/cjs/unity-integration/components/UnityAssetStoreBrowser.js +1233 -757
- package/dist/cjs/unity-integration/components/UnityProjectBrowser.js +1240 -768
- package/dist/cjs/unreal-integration/UnrealImport.js +391 -412
- package/dist/cjs/unreal-integration/UnrealLiveLink.js +1102 -1137
- package/dist/cjs/unreal-integration/UnrealMarketplace.js +436 -473
- package/dist/cjs/unreal-integration/components/UnrealProjectBrowser.js +1150 -767
- package/dist/cjs/xr/ARVR.js +167 -175
- package/dist/esm/accessibility/Accessibility.js +160 -164
- package/dist/esm/ai/AI.js +310 -293
- package/dist/esm/ai/BehaviorTree.js +1057 -1112
- package/dist/esm/ai/StateMachine.js +709 -755
- package/dist/esm/animation/Animation.js +237 -240
- package/dist/esm/audio/AudioAdvanced.js +239 -235
- package/dist/esm/audio/AudioBridge.js +448 -434
- package/dist/esm/audio/AudioManager.js +243 -258
- package/dist/esm/build-cloud/BuildOrchestration.js +1071 -1097
- package/dist/esm/build-cloud/GodotBuildCloud.js +647 -669
- package/dist/esm/build-cloud/UnityBuildCloud.js +571 -609
- package/dist/esm/build-cloud/UnrealBuildCloud.js +615 -634
- package/dist/esm/core/EventBus.js +52 -55
- package/dist/esm/core/GameClock.js +63 -65
- package/dist/esm/core/GameConfig.js +77 -78
- package/dist/esm/core/GameLoop.js +81 -88
- package/dist/esm/core/ServiceLocator.js +63 -64
- package/dist/esm/core/Validation.js +82 -81
- package/dist/esm/core/math.js +109 -111
- package/dist/esm/devtools/DevTools.js +546 -562
- package/dist/esm/devtools/DeveloperExperience.js +535 -558
- package/dist/esm/devtools/GameplayAnalytics.js +647 -645
- package/dist/esm/dialogue/DialogueSystem.js +998 -985
- package/dist/esm/docs/DocGenerator.js +342 -363
- package/dist/esm/ecs/World.js +358 -370
- package/dist/esm/editor/AchievementEditor.js +584 -635
- package/dist/esm/editor/AdvancedEditor.js +191 -190
- package/dist/esm/editor/AnimationRetargeting.js +700 -740
- package/dist/esm/editor/AssetBrowser.js +1078 -1159
- package/dist/esm/editor/AssetManager.js +188 -191
- package/dist/esm/editor/ConsolePro.js +977 -1060
- package/dist/esm/editor/CraftingEditor.js +684 -729
- package/dist/esm/editor/DebugTools.js +194 -184
- package/dist/esm/editor/DialogueSystem.js +849 -900
- package/dist/esm/editor/LeaderboardSystem.js +433 -482
- package/dist/esm/editor/NiceGameEditor.js +1908 -1200
- package/dist/esm/editor/PrefabSystem.js +777 -837
- package/dist/esm/editor/ProfilerPanel.js +654 -699
- package/dist/esm/editor/QuestEditor.js +795 -838
- package/dist/esm/editor/ReplaySystem.js +591 -633
- package/dist/esm/editor/SceneEditor.js +189 -199
- package/dist/esm/editor/ScreenshotMode.js +628 -687
- package/dist/esm/editor/ShaderGraph.js +1565 -1581
- package/dist/esm/editor/TimelineEditor.js +733 -777
- package/dist/esm/editor/UndoRedoPro.js +835 -903
- package/dist/esm/editor/VRARMode.js +586 -644
- package/dist/esm/engine/NiceGameEngine.js +142 -163
- package/dist/esm/engine/SaveSystem.js +447 -494
- package/dist/esm/enterprise/Enterprise.js +265 -260
- package/dist/esm/export/BevyExporter.js +929 -966
- package/dist/esm/export/CocosExporter.js +646 -672
- package/dist/esm/export/Construct3Exporter.js +785 -793
- package/dist/esm/export/DefoldExporter.js +1030 -1068
- package/dist/esm/export/GDevelopExporter.js +676 -707
- package/dist/esm/export/GameMakerExporter.js +793 -804
- package/dist/esm/export/GodotExporter.js +1004 -1044
- package/dist/esm/export/MinecraftBedrockExporter.js +575 -577
- package/dist/esm/export/MonoGameExporter.js +1267 -1292
- package/dist/esm/export/Pico8Exporter.js +768 -811
- package/dist/esm/export/PlatformExporter.js +193 -205
- package/dist/esm/export/RPGMakerExporter.js +862 -878
- package/dist/esm/export/RobloxExporter.js +885 -918
- package/dist/esm/export/Solar2DExporter.js +1220 -1255
- package/dist/esm/export/ThreeJSExporter.js +1007 -1072
- package/dist/esm/export/Tic80Exporter.js +1212 -1266
- package/dist/esm/export/UnityExporter.js +1117 -1130
- package/dist/esm/export/UnrealExporter.js +891 -918
- package/dist/esm/export/WebExporter.js +933 -969
- package/dist/esm/export/index.js +86 -71
- package/dist/esm/godot-integration/GodotAssetLibrary.js +663 -691
- package/dist/esm/godot-integration/GodotImport.js +935 -1026
- package/dist/esm/godot-integration/GodotLiveLink.js +918 -944
- package/dist/esm/godot-integration/components/GodotProjectBrowser.js +912 -610
- package/dist/esm/i18n/I18n.js +871 -899
- package/dist/esm/i18n/useTranslation.js +88 -88
- package/dist/esm/import/AsepriteImporter.js +637 -715
- package/dist/esm/import/DragonBonesImporter.js +417 -460
- package/dist/esm/import/GameMakerImporter.js +491 -520
- package/dist/esm/import/GodotSceneImporter.js +767 -821
- package/dist/esm/import/LDtkImporter.js +415 -453
- package/dist/esm/import/Live2DImporter.js +477 -517
- package/dist/esm/import/NdgFormat.js +410 -456
- package/dist/esm/import/OgmoImporter.js +446 -492
- package/dist/esm/import/RPGMakerImporter.js +431 -476
- package/dist/esm/import/SceneImporter.js +385 -422
- package/dist/esm/import/SpineImporter.js +491 -545
- package/dist/esm/import/SpriterImporter.js +570 -612
- package/dist/esm/import/TiledMapImporter.js +790 -845
- package/dist/esm/import/UnitySceneImporter.js +666 -702
- package/dist/esm/import/index.js +247 -258
- package/dist/esm/index.js +1332 -188
- package/dist/esm/input/GamepadNavigation.js +187 -204
- package/dist/esm/input/InputManager.js +401 -420
- package/dist/esm/input/useGamepads.js +72 -80
- package/dist/esm/integration/IconSprite.js +143 -255
- package/dist/esm/inventory/InventorySystem.js +925 -994
- package/dist/esm/kids/KidMode.js +1003 -1021
- package/dist/esm/kids/KidTools.js +573 -593
- package/dist/esm/monetization/Monetization.js +180 -176
- package/dist/esm/multiplayer/LocalMultiplayer.js +290 -286
- package/dist/esm/multiplayer/MiniGameTypes.js +58 -58
- package/dist/esm/native-engine/AnimationSystem.js +735 -805
- package/dist/esm/native-engine/AssetPipeline.js +456 -514
- package/dist/esm/native-engine/AudioEngine.js +765 -803
- package/dist/esm/native-engine/InputSystem.js +1079 -1144
- package/dist/esm/native-engine/NetworkingSystem.js +740 -792
- package/dist/esm/native-engine/PhysicsEngine.js +585 -606
- package/dist/esm/native-engine/RenderingEngine.js +304 -349
- package/dist/esm/native-engine/SceneGraph.js +773 -807
- package/dist/esm/network/MultiplayerTransport.js +99 -131
- package/dist/esm/network/Networking.js +556 -563
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AbortController.js +22 -28
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js +41 -47
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js +36 -42
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js +11 -14
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Errors.js +111 -134
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js +132 -157
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js +40 -52
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js +6 -7
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpClient.js +42 -47
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js +496 -571
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnection.js +828 -952
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js +126 -145
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js +14 -23
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ILogger.js +12 -25
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ITransport.js +15 -24
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js +109 -120
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Loggers.js +11 -13
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js +151 -184
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js +159 -195
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js +91 -104
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Subject.js +31 -34
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js +17 -20
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Utils.js +230 -248
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js +136 -156
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js +77 -84
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/index.js +31 -12
- package/dist/esm/node_modules/@microsoft/signalr/dist/esm/pkg-version.js +4 -3
- package/dist/esm/pathfinding/Pathfinding.js +249 -262
- package/dist/esm/performance/AssetStreaming.js +567 -634
- package/dist/esm/performance/BenchmarkSuite.js +285 -310
- package/dist/esm/performance/DeltaCompression.js +478 -525
- package/dist/esm/performance/DeterministicPhysics.js +479 -497
- package/dist/esm/performance/ECSOptimization.js +653 -694
- package/dist/esm/performance/GameSaveSystem.js +515 -555
- package/dist/esm/performance/HotReload.js +454 -499
- package/dist/esm/performance/InputRecording.js +520 -560
- package/dist/esm/performance/InterestManagement.js +460 -499
- package/dist/esm/performance/LocalizationRuntime.js +382 -422
- package/dist/esm/performance/MemoryManagement.js +415 -469
- package/dist/esm/performance/ModSupport.js +455 -495
- package/dist/esm/performance/MultiThreadedPhysics.js +408 -442
- package/dist/esm/performance/NetworkPrediction.js +436 -481
- package/dist/esm/performance/ObjectPooling.js +582 -616
- package/dist/esm/performance/Performance.js +182 -189
- package/dist/esm/performance/PerformanceAdvanced.js +621 -636
- package/dist/esm/performance/WebGPURenderer.js +660 -682
- package/dist/esm/physics/PhysicsAdvanced.js +359 -378
- package/dist/esm/physics/PhysicsEngine2D.js +393 -426
- package/dist/esm/plugins/PluginSDK.js +435 -465
- package/dist/esm/plugins/PluginTestKit.js +315 -329
- package/dist/esm/procedural/Procedural.js +248 -253
- package/dist/esm/procedural/WorldBuilding.js +316 -313
- package/dist/esm/quest/QuestSystem.js +982 -931
- package/dist/esm/release/MobileExport.js +163 -162
- package/dist/esm/release/Release.js +234 -237
- package/dist/esm/rendering/Camera2D.js +122 -123
- package/dist/esm/rendering/Renderer2D.js +323 -334
- package/dist/esm/rendering/WebGPURenderPipeline.js +647 -650
- package/dist/esm/runtime3d/Runtime3D.js +368 -377
- package/dist/esm/runtime3d/SceneEditor3D.js +268 -262
- package/dist/esm/scene/SceneManager.js +178 -192
- package/dist/esm/scripting/GraphToAST.js +576 -546
- package/dist/esm/scripting/LanguageExporter.js +263 -278
- package/dist/esm/scripting/NodeGraph.js +550 -569
- package/dist/esm/scripting/ScriptAST.js +45 -38
- package/dist/esm/scripting/VisualScripting2.js +1025 -1064
- package/dist/esm/scripting/exporters/CSharpExporter.js +465 -495
- package/dist/esm/scripting/exporters/GDScriptExporter.js +391 -441
- package/dist/esm/scripting/exporters/LuaExporter.js +407 -446
- package/dist/esm/scripting/exporters/PythonExporter.js +485 -548
- package/dist/esm/scripting/exporters/RustExporter.js +460 -511
- package/dist/esm/scripting/exporters/TypeScriptExporter.js +506 -555
- package/dist/esm/social/Social.js +77 -79
- package/dist/esm/systems/LightingSystem.js +855 -930
- package/dist/esm/systems/ParticleSystem2.js +1453 -1450
- package/dist/esm/systems/PhysicsDebugSystem.js +1078 -1140
- package/dist/esm/systems/TerrainSystem.js +996 -1097
- package/dist/esm/templates/ActionTemplates.js +307 -308
- package/dist/esm/templates/FightingTemplate.js +439 -462
- package/dist/esm/templates/MetroidvaniaTemplate.js +391 -404
- package/dist/esm/templates/PartyTemplates.js +206 -201
- package/dist/esm/templates/PuzzleTemplates.js +260 -260
- package/dist/esm/templates/RPGTemplates.js +172 -177
- package/dist/esm/templates/SportsTemplates.js +251 -249
- package/dist/esm/templates/StrategyTemplates.js +158 -152
- package/dist/esm/templates/SurvivalTemplate.js +367 -379
- package/dist/esm/templates/WaveDefense.js +501 -525
- package/dist/esm/tilemap/Tilemap.js +209 -213
- package/dist/esm/tutorials/TutorialBranching.js +399 -416
- package/dist/esm/tutorials/TutorialEngine.js +893 -930
- package/dist/esm/tutorials/TutorialOverlay.js +603 -639
- package/dist/esm/tutorials/content/Tutorials_T05_T08.js +792 -808
- package/dist/esm/tutorials/content/Tutorials_T09_T11.js +740 -755
- package/dist/esm/tutorials/content/Tutorials_T12_T15.js +759 -777
- package/dist/esm/ui/GameUI.js +296 -311
- package/dist/esm/unity-integration/UnityAssetStore.js +704 -740
- package/dist/esm/unity-integration/UnityImport.js +1071 -1175
- package/dist/esm/unity-integration/UnityLiveLink.js +938 -980
- package/dist/esm/unity-integration/components/UnityAssetStoreBrowser.js +1234 -756
- package/dist/esm/unity-integration/components/UnityProjectBrowser.js +1241 -767
- package/dist/esm/unreal-integration/UnrealImport.js +395 -411
- package/dist/esm/unreal-integration/UnrealLiveLink.js +1105 -1136
- package/dist/esm/unreal-integration/UnrealMarketplace.js +442 -472
- package/dist/esm/unreal-integration/components/UnrealProjectBrowser.js +1151 -766
- package/dist/esm/xr/ARVR.js +181 -174
- package/package.json +7 -12
|
@@ -1,944 +1,908 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/* ────────────────────────────────────────────────────────────────
|
|
6
|
-
Roblox Exporter — Roblox Studio Project Export
|
|
7
|
-
|
|
8
|
-
Exports Nice2Dev projects to Roblox Studio format including:
|
|
9
|
-
- Luau scripts (.lua)
|
|
10
|
-
- Model instances (.rbxmx XML)
|
|
11
|
-
- Module scripts
|
|
12
|
-
- Place file structure
|
|
13
|
-
──────────────────────────────────────────────────────────────── */
|
|
14
|
-
/* ── Roblox Exporter Implementation ───────────────────────────── */
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const PlatformExporter = require("./PlatformExporter.js");
|
|
15
4
|
class RobloxExporter extends PlatformExporter.PlatformExporter {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.platformId = "roblox";
|
|
8
|
+
this.platformInfo = {
|
|
9
|
+
id: "roblox",
|
|
10
|
+
name: "Roblox Studio",
|
|
11
|
+
description: "Roblox platform with Luau scripting language",
|
|
12
|
+
website: "https://create.roblox.com",
|
|
13
|
+
features: [
|
|
14
|
+
"3d-rendering",
|
|
15
|
+
"physics-3d",
|
|
16
|
+
"audio",
|
|
17
|
+
"networking",
|
|
18
|
+
"ui-system",
|
|
19
|
+
"particles",
|
|
20
|
+
"animation"
|
|
21
|
+
],
|
|
22
|
+
supportedAssets: ["audio", "script", "scene", "prefab", "particleSystem", "texture", "data"],
|
|
23
|
+
exportFormats: [".lua", ".rbxmx", ".rbxlx"]
|
|
24
|
+
};
|
|
25
|
+
this.projectName = "Nice2DevGame";
|
|
26
|
+
this.useStrictMode = true;
|
|
27
|
+
}
|
|
28
|
+
async doExport(project, options) {
|
|
29
|
+
this.projectName = (options.projectName ?? project.name).replace(/[^a-zA-Z0-9_]/g, "_");
|
|
30
|
+
const platformOpts = options.platformOptions ?? {};
|
|
31
|
+
this.useStrictMode = platformOpts.strictMode !== false;
|
|
32
|
+
await this.generateFolderStructure(project, options);
|
|
33
|
+
await this.generateCoreScripts(project, options);
|
|
34
|
+
await this.generateServicesSetup(project, options);
|
|
35
|
+
for (const scene of project.scenes) {
|
|
36
|
+
await this.exportScene(scene, project, options);
|
|
38
37
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const platformOpts = options.platformOptions ?? {};
|
|
42
|
-
this.useStrictMode = platformOpts.strictMode !== false;
|
|
43
|
-
// Generate folder structure
|
|
44
|
-
await this.generateFolderStructure(project, options);
|
|
45
|
-
// Generate core scripts
|
|
46
|
-
await this.generateCoreScripts(project, options);
|
|
47
|
-
// Generate services setup
|
|
48
|
-
await this.generateServicesSetup(project, options);
|
|
49
|
-
// Export scenes as places/models
|
|
50
|
-
for (const scene of project.scenes) {
|
|
51
|
-
await this.exportScene(scene, project, options);
|
|
52
|
-
}
|
|
53
|
-
// Export prefabs as models
|
|
54
|
-
for (const prefab of project.prefabs) {
|
|
55
|
-
await this.exportPrefab(prefab, options);
|
|
56
|
-
}
|
|
57
|
-
// Generate client scripts if enabled
|
|
58
|
-
if (platformOpts.includeClientScripts !== false) {
|
|
59
|
-
await this.generateClientScripts(project, options);
|
|
60
|
-
}
|
|
61
|
-
// Generate server scripts if enabled
|
|
62
|
-
if (platformOpts.includeServerScripts !== false) {
|
|
63
|
-
await this.generateServerScripts(project, options);
|
|
64
|
-
}
|
|
38
|
+
for (const prefab of project.prefabs) {
|
|
39
|
+
await this.exportPrefab(prefab, options);
|
|
65
40
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Generated from Nice2Dev project v${project.version}
|
|
72
|
-
|
|
73
|
-
## Folder Structure
|
|
74
|
-
|
|
75
|
-
- \`ServerScriptService/\` - Server-side scripts
|
|
76
|
-
- \`ReplicatedStorage/\` - Shared modules and assets
|
|
77
|
-
- \`StarterPlayer/StarterPlayerScripts/\` - Client scripts
|
|
78
|
-
- \`StarterGui/\` - UI elements
|
|
79
|
-
- \`Workspace/\` - Game world objects
|
|
80
|
-
|
|
81
|
-
## Setup Instructions
|
|
82
|
-
|
|
83
|
-
1. Open Roblox Studio
|
|
84
|
-
2. Create a new place or open existing
|
|
85
|
-
3. Import the .rbxmx model files
|
|
86
|
-
4. Copy Lua scripts to appropriate services
|
|
87
|
-
5. Configure game settings as needed
|
|
88
|
-
|
|
89
|
-
## Notes
|
|
90
|
-
|
|
91
|
-
- Textures and audio assets need to be uploaded to Roblox and IDs updated
|
|
92
|
-
- Physics settings may need adjustment for Roblox's scale
|
|
93
|
-
`;
|
|
94
|
-
this.addTextFile('README.md', readme);
|
|
41
|
+
if (platformOpts.includeClientScripts !== false) {
|
|
42
|
+
await this.generateClientScripts(project, options);
|
|
43
|
+
}
|
|
44
|
+
if (platformOpts.includeServerScripts !== false) {
|
|
45
|
+
await this.generateServerScripts(project, options);
|
|
95
46
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
GameManager.Settings = {
|
|
124
|
-
GameWidth = ${project.settings.resolution.width},
|
|
125
|
-
GameHeight = ${project.settings.resolution.height},
|
|
126
|
-
MasterVolume = ${project.settings.audio.masterVolume},
|
|
127
|
-
PhysicsEnabled = ${project.settings.physics.enabled},
|
|
128
|
-
GravityX = ${project.settings.physics.gravity.x},
|
|
129
|
-
GravityY = ${project.settings.physics.gravity.y},
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function GameManager.new()
|
|
133
|
-
local self = setmetatable({}, GameManager)
|
|
134
|
-
return self
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
function GameManager:Initialize()
|
|
138
|
-
-- Apply gravity settings
|
|
139
|
-
workspace.Gravity = math.abs(self.Settings.GravityY)
|
|
140
|
-
|
|
141
|
-
-- Set up game loop
|
|
142
|
-
RunService.Heartbeat:Connect(function(deltaTime)
|
|
143
|
-
if not gameState.isPaused then
|
|
144
|
-
self:Update(deltaTime)
|
|
145
|
-
end
|
|
146
|
-
end)
|
|
147
|
-
|
|
148
|
-
print("[GameManager] Initialized")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
function GameManager:Update(deltaTime: number)
|
|
152
|
-
-- Update all registered entities
|
|
153
|
-
for id, entity in pairs(gameState.entities) do
|
|
154
|
-
if entity.Update then
|
|
155
|
-
entity:Update(deltaTime)
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
function GameManager:RegisterEntity(id: string, entity: any)
|
|
161
|
-
gameState.entities[id] = entity
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
function GameManager:UnregisterEntity(id: string)
|
|
165
|
-
gameState.entities[id] = nil
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
function GameManager:GetEntity(id: string)
|
|
169
|
-
return gameState.entities[id]
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
function GameManager:SetVariable(key: string, value: any)
|
|
173
|
-
gameState.globalVariables[key] = value
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
function GameManager:GetVariable(key: string): any
|
|
177
|
-
return gameState.globalVariables[key]
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
function GameManager:Pause()
|
|
181
|
-
gameState.isPaused = true
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
function GameManager:Resume()
|
|
185
|
-
gameState.isPaused = false
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
function GameManager:IsPaused(): boolean
|
|
189
|
-
return gameState.isPaused
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
return GameManager
|
|
47
|
+
}
|
|
48
|
+
/* ── Folder Structure ───────────────────────────────────────── */
|
|
49
|
+
async generateFolderStructure(project, _options) {
|
|
50
|
+
const readme = `# ${project.name} - Roblox Export
|
|
51
|
+
|
|
52
|
+
Generated from Nice2Dev project v${project.version}
|
|
53
|
+
|
|
54
|
+
## Folder Structure
|
|
55
|
+
|
|
56
|
+
- \`ServerScriptService/\` - Server-side scripts
|
|
57
|
+
- \`ReplicatedStorage/\` - Shared modules and assets
|
|
58
|
+
- \`StarterPlayer/StarterPlayerScripts/\` - Client scripts
|
|
59
|
+
- \`StarterGui/\` - UI elements
|
|
60
|
+
- \`Workspace/\` - Game world objects
|
|
61
|
+
|
|
62
|
+
## Setup Instructions
|
|
63
|
+
|
|
64
|
+
1. Open Roblox Studio
|
|
65
|
+
2. Create a new place or open existing
|
|
66
|
+
3. Import the .rbxmx model files
|
|
67
|
+
4. Copy Lua scripts to appropriate services
|
|
68
|
+
5. Configure game settings as needed
|
|
69
|
+
|
|
70
|
+
## Notes
|
|
71
|
+
|
|
72
|
+
- Textures and audio assets need to be uploaded to Roblox and IDs updated
|
|
73
|
+
- Physics settings may need adjustment for Roblox's scale
|
|
193
74
|
`;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
self:SetPosition(targetPosition.X, targetPosition.Y, targetPosition.Z)
|
|
293
|
-
else
|
|
294
|
-
local newPos = currentPos + direction * speed * deltaTime
|
|
295
|
-
self:SetPosition(newPos.X, newPos.Y, newPos.Z)
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
function EntityBase:LookAt(targetPosition: Vector3)
|
|
300
|
-
if self.Instance and self.Instance:IsA("BasePart") then
|
|
301
|
-
self.Instance.CFrame = CFrame.lookAt(self.Instance.Position, targetPosition)
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
return EntityBase
|
|
75
|
+
this.addTextFile("README.md", readme);
|
|
76
|
+
}
|
|
77
|
+
/* ── Core Scripts ───────────────────────────────────────────── */
|
|
78
|
+
async generateCoreScripts(project, _options) {
|
|
79
|
+
const gameManagerModule = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
80
|
+
Game Manager Module
|
|
81
|
+
Generated from Nice2Dev project: ${project.name}
|
|
82
|
+
|
|
83
|
+
Central game state and utility management.
|
|
84
|
+
]]
|
|
85
|
+
|
|
86
|
+
local GameManager = {}
|
|
87
|
+
GameManager.__index = GameManager
|
|
88
|
+
|
|
89
|
+
-- Services
|
|
90
|
+
local Players = game:GetService("Players")
|
|
91
|
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
92
|
+
local RunService = game:GetService("RunService")
|
|
93
|
+
|
|
94
|
+
-- Game State
|
|
95
|
+
local gameState = {
|
|
96
|
+
isPaused = false,
|
|
97
|
+
currentScene = nil,
|
|
98
|
+
entities = {},
|
|
99
|
+
globalVariables = {},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
-- Settings from Nice2Dev project
|
|
103
|
+
GameManager.Settings = {
|
|
104
|
+
GameWidth = ${project.settings.resolution.width},
|
|
105
|
+
GameHeight = ${project.settings.resolution.height},
|
|
106
|
+
MasterVolume = ${project.settings.audio.masterVolume},
|
|
107
|
+
PhysicsEnabled = ${project.settings.physics.enabled},
|
|
108
|
+
GravityX = ${project.settings.physics.gravity.x},
|
|
109
|
+
GravityY = ${project.settings.physics.gravity.y},
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function GameManager.new()
|
|
113
|
+
local self = setmetatable({}, GameManager)
|
|
114
|
+
return self
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
function GameManager:Initialize()
|
|
118
|
+
-- Apply gravity settings
|
|
119
|
+
workspace.Gravity = math.abs(self.Settings.GravityY)
|
|
120
|
+
|
|
121
|
+
-- Set up game loop
|
|
122
|
+
RunService.Heartbeat:Connect(function(deltaTime)
|
|
123
|
+
if not gameState.isPaused then
|
|
124
|
+
self:Update(deltaTime)
|
|
125
|
+
end
|
|
126
|
+
end)
|
|
127
|
+
|
|
128
|
+
print("[GameManager] Initialized")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
function GameManager:Update(deltaTime: number)
|
|
132
|
+
-- Update all registered entities
|
|
133
|
+
for id, entity in pairs(gameState.entities) do
|
|
134
|
+
if entity.Update then
|
|
135
|
+
entity:Update(deltaTime)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
function GameManager:RegisterEntity(id: string, entity: any)
|
|
141
|
+
gameState.entities[id] = entity
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
function GameManager:UnregisterEntity(id: string)
|
|
145
|
+
gameState.entities[id] = nil
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
function GameManager:GetEntity(id: string)
|
|
149
|
+
return gameState.entities[id]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
function GameManager:SetVariable(key: string, value: any)
|
|
153
|
+
gameState.globalVariables[key] = value
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
function GameManager:GetVariable(key: string): any
|
|
157
|
+
return gameState.globalVariables[key]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
function GameManager:Pause()
|
|
161
|
+
gameState.isPaused = true
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
function GameManager:Resume()
|
|
165
|
+
gameState.isPaused = false
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
function GameManager:IsPaused(): boolean
|
|
169
|
+
return gameState.isPaused
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
return GameManager
|
|
306
173
|
`;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
Nice2Dev
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
return Utility
|
|
174
|
+
this.addTextFile("ReplicatedStorage/Modules/GameManager.lua", gameManagerModule);
|
|
175
|
+
const entityBaseModule = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
176
|
+
Entity Base Module
|
|
177
|
+
Base class for all Nice2Dev entities
|
|
178
|
+
]]
|
|
179
|
+
|
|
180
|
+
local EntityBase = {}
|
|
181
|
+
EntityBase.__index = EntityBase
|
|
182
|
+
|
|
183
|
+
export type Entity = {
|
|
184
|
+
Id: string,
|
|
185
|
+
Name: string,
|
|
186
|
+
Tags: {string},
|
|
187
|
+
Instance: Instance?,
|
|
188
|
+
|
|
189
|
+
Start: (self: Entity) -> (),
|
|
190
|
+
Update: (self: Entity, deltaTime: number) -> (),
|
|
191
|
+
Destroy: (self: Entity) -> (),
|
|
192
|
+
HasTag: (self: Entity, tag: string) -> boolean,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function EntityBase.new(id: string, name: string): Entity
|
|
196
|
+
local self = setmetatable({}, EntityBase)
|
|
197
|
+
self.Id = id
|
|
198
|
+
self.Name = name
|
|
199
|
+
self.Tags = {}
|
|
200
|
+
self.Instance = nil
|
|
201
|
+
return self :: Entity
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
function EntityBase:Start()
|
|
205
|
+
-- Override in derived entities
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
function EntityBase:Update(deltaTime: number)
|
|
209
|
+
-- Override in derived entities
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
function EntityBase:Destroy()
|
|
213
|
+
if self.Instance then
|
|
214
|
+
self.Instance:Destroy()
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
function EntityBase:HasTag(tag: string): boolean
|
|
219
|
+
for _, t in ipairs(self.Tags) do
|
|
220
|
+
if t == tag then
|
|
221
|
+
return true
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
return false
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
function EntityBase:AddTag(tag: string)
|
|
228
|
+
if not self:HasTag(tag) then
|
|
229
|
+
table.insert(self.Tags, tag)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
function EntityBase:RemoveTag(tag: string)
|
|
234
|
+
for i, t in ipairs(self.Tags) do
|
|
235
|
+
if t == tag then
|
|
236
|
+
table.remove(self.Tags, i)
|
|
237
|
+
return
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
function EntityBase:SetPosition(x: number, y: number, z: number?)
|
|
243
|
+
if self.Instance and self.Instance:IsA("BasePart") then
|
|
244
|
+
self.Instance.Position = Vector3.new(x, y, z or 0)
|
|
245
|
+
elseif self.Instance and self.Instance:IsA("Model") then
|
|
246
|
+
local primary = self.Instance.PrimaryPart
|
|
247
|
+
if primary then
|
|
248
|
+
self.Instance:SetPrimaryPartCFrame(CFrame.new(x, y, z or 0))
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
function EntityBase:GetPosition(): Vector3
|
|
254
|
+
if self.Instance and self.Instance:IsA("BasePart") then
|
|
255
|
+
return self.Instance.Position
|
|
256
|
+
elseif self.Instance and self.Instance:IsA("Model") then
|
|
257
|
+
local primary = self.Instance.PrimaryPart
|
|
258
|
+
if primary then
|
|
259
|
+
return primary.Position
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
return Vector3.new(0, 0, 0)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
function EntityBase:MoveTowards(targetPosition: Vector3, speed: number, deltaTime: number)
|
|
266
|
+
local currentPos = self:GetPosition()
|
|
267
|
+
local direction = (targetPosition - currentPos).Unit
|
|
268
|
+
local distance = (targetPosition - currentPos).Magnitude
|
|
269
|
+
|
|
270
|
+
if distance <= speed * deltaTime then
|
|
271
|
+
self:SetPosition(targetPosition.X, targetPosition.Y, targetPosition.Z)
|
|
272
|
+
else
|
|
273
|
+
local newPos = currentPos + direction * speed * deltaTime
|
|
274
|
+
self:SetPosition(newPos.X, newPos.Y, newPos.Z)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
function EntityBase:LookAt(targetPosition: Vector3)
|
|
279
|
+
if self.Instance and self.Instance:IsA("BasePart") then
|
|
280
|
+
self.Instance.CFrame = CFrame.lookAt(self.Instance.Position, targetPosition)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
return EntityBase
|
|
419
285
|
`;
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
286
|
+
this.addTextFile("ReplicatedStorage/Modules/EntityBase.lua", entityBaseModule);
|
|
287
|
+
const utilityModule = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
288
|
+
Nice2Dev Utility Module
|
|
289
|
+
Common utility functions for game development
|
|
290
|
+
]]
|
|
291
|
+
|
|
292
|
+
local Utility = {}
|
|
293
|
+
|
|
294
|
+
-- Math Utilities
|
|
295
|
+
function Utility.Lerp(a: number, b: number, t: number): number
|
|
296
|
+
return a + (b - a) * math.clamp(t, 0, 1)
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
function Utility.LerpVector3(a: Vector3, b: Vector3, t: number): Vector3
|
|
300
|
+
return a:Lerp(b, math.clamp(t, 0, 1))
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
function Utility.LerpColor3(a: Color3, b: Color3, t: number): Color3
|
|
304
|
+
return a:Lerp(b, math.clamp(t, 0, 1))
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
function Utility.Remap(value: number, inMin: number, inMax: number, outMin: number, outMax: number): number
|
|
308
|
+
return outMin + (value - inMin) * (outMax - outMin) / (inMax - inMin)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
function Utility.RandomPointInCircle(center: Vector3, radius: number): Vector3
|
|
312
|
+
local angle = math.random() * math.pi * 2
|
|
313
|
+
local distance = math.sqrt(math.random()) * radius
|
|
314
|
+
return center + Vector3.new(
|
|
315
|
+
math.cos(angle) * distance,
|
|
316
|
+
0,
|
|
317
|
+
math.sin(angle) * distance
|
|
318
|
+
)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
function Utility.RandomPointInSphere(center: Vector3, radius: number): Vector3
|
|
322
|
+
local theta = math.random() * math.pi * 2
|
|
323
|
+
local phi = math.acos(2 * math.random() - 1)
|
|
324
|
+
local r = radius * math.random() ^ (1/3)
|
|
325
|
+
|
|
326
|
+
return center + Vector3.new(
|
|
327
|
+
r * math.sin(phi) * math.cos(theta),
|
|
328
|
+
r * math.sin(phi) * math.sin(theta),
|
|
329
|
+
r * math.cos(phi)
|
|
330
|
+
)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
-- Distance Utilities
|
|
334
|
+
function Utility.Distance2D(a: Vector3, b: Vector3): number
|
|
335
|
+
local dx = a.X - b.X
|
|
336
|
+
local dz = a.Z - b.Z
|
|
337
|
+
return math.sqrt(dx * dx + dz * dz)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
function Utility.Distance3D(a: Vector3, b: Vector3): number
|
|
341
|
+
return (a - b).Magnitude
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
-- Instance Utilities
|
|
345
|
+
function Utility.FindFirstChildWithTag(parent: Instance, tag: string): Instance?
|
|
346
|
+
local CollectionService = game:GetService("CollectionService")
|
|
347
|
+
for _, child in ipairs(parent:GetChildren()) do
|
|
348
|
+
if CollectionService:HasTag(child, tag) then
|
|
349
|
+
return child
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
return nil
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
function Utility.FindChildrenWithTag(parent: Instance, tag: string): {Instance}
|
|
356
|
+
local CollectionService = game:GetService("CollectionService")
|
|
357
|
+
local result = {}
|
|
358
|
+
for _, child in ipairs(parent:GetDescendants()) do
|
|
359
|
+
if CollectionService:HasTag(child, tag) then
|
|
360
|
+
table.insert(result, child)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
return result
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
-- Timer Utility
|
|
367
|
+
function Utility.CreateTimer(duration: number, callback: () -> ()): thread
|
|
368
|
+
return task.spawn(function()
|
|
369
|
+
task.wait(duration)
|
|
370
|
+
callback()
|
|
371
|
+
end)
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
function Utility.CreateRepeatingTimer(interval: number, callback: () -> boolean): thread
|
|
375
|
+
return task.spawn(function()
|
|
376
|
+
while true do
|
|
377
|
+
task.wait(interval)
|
|
378
|
+
local shouldContinue = callback()
|
|
379
|
+
if not shouldContinue then
|
|
380
|
+
break
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
-- Spawn Utility
|
|
387
|
+
function Utility.SpawnModel(model: Model, position: Vector3, parent: Instance?): Model
|
|
388
|
+
local clone = model:Clone()
|
|
389
|
+
if clone.PrimaryPart then
|
|
390
|
+
clone:SetPrimaryPartCFrame(CFrame.new(position))
|
|
391
|
+
end
|
|
392
|
+
clone.Parent = parent or workspace
|
|
393
|
+
return clone
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
return Utility
|
|
467
397
|
`;
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
local
|
|
481
|
-
local
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
--
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
|
|
514
|
-
-- Left click
|
|
515
|
-
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
|
|
516
|
-
-- Right click
|
|
517
|
-
end
|
|
518
|
-
end)
|
|
519
|
-
|
|
520
|
-
UserInputService.InputEnded:Connect(function(input, gameProcessed)
|
|
521
|
-
if input.UserInputType == Enum.UserInputType.Keyboard then
|
|
522
|
-
inputState.keysDown[input.KeyCode] = nil
|
|
523
|
-
end
|
|
524
|
-
end)
|
|
525
|
-
|
|
526
|
-
-- Mouse tracking
|
|
527
|
-
UserInputService.InputChanged:Connect(function(input)
|
|
528
|
-
if input.UserInputType == Enum.UserInputType.MouseMovement then
|
|
529
|
-
inputState.mousePosition = Vector2.new(input.Position.X, input.Position.Y)
|
|
530
|
-
end
|
|
531
|
-
end)
|
|
532
|
-
|
|
533
|
-
-- Helper functions
|
|
534
|
-
local function IsKeyDown(keyCode: Enum.KeyCode): boolean
|
|
535
|
-
return inputState.keysDown[keyCode] ~= nil
|
|
536
|
-
end
|
|
537
|
-
|
|
538
|
-
local function GetMoveDirection(): Vector3
|
|
539
|
-
local direction = Vector3.new(0, 0, 0)
|
|
540
|
-
|
|
541
|
-
if IsKeyDown(Enum.KeyCode.W) or IsKeyDown(Enum.KeyCode.Up) then
|
|
542
|
-
direction = direction + Vector3.new(0, 0, -1)
|
|
543
|
-
end
|
|
544
|
-
if IsKeyDown(Enum.KeyCode.S) or IsKeyDown(Enum.KeyCode.Down) then
|
|
545
|
-
direction = direction + Vector3.new(0, 0, 1)
|
|
546
|
-
end
|
|
547
|
-
if IsKeyDown(Enum.KeyCode.A) or IsKeyDown(Enum.KeyCode.Left) then
|
|
548
|
-
direction = direction + Vector3.new(-1, 0, 0)
|
|
549
|
-
end
|
|
550
|
-
if IsKeyDown(Enum.KeyCode.D) or IsKeyDown(Enum.KeyCode.Right) then
|
|
551
|
-
direction = direction + Vector3.new(1, 0, 0)
|
|
552
|
-
end
|
|
553
|
-
|
|
554
|
-
if direction.Magnitude > 0 then
|
|
555
|
-
direction = direction.Unit
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
return direction
|
|
559
|
-
end
|
|
560
|
-
|
|
561
|
-
-- Client update loop
|
|
562
|
-
RunService.RenderStepped:Connect(function(deltaTime)
|
|
563
|
-
inputState.moveDirection = GetMoveDirection()
|
|
564
|
-
|
|
565
|
-
-- Update client-side effects, animations, etc.
|
|
566
|
-
end)
|
|
567
|
-
|
|
568
|
-
print("[ClientController] Initialized")
|
|
398
|
+
this.addTextFile("ReplicatedStorage/Modules/Utility.lua", utilityModule);
|
|
399
|
+
}
|
|
400
|
+
/* ── Services Setup ─────────────────────────────────────────── */
|
|
401
|
+
async generateServicesSetup(project, options) {
|
|
402
|
+
const platformOpts = options.platformOptions ?? {};
|
|
403
|
+
const genre = platformOpts.genre ?? "adventure";
|
|
404
|
+
const initScript = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
405
|
+
Game Initialization Script
|
|
406
|
+
Generated from Nice2Dev project: ${project.name}
|
|
407
|
+
Genre: ${genre}
|
|
408
|
+
]]
|
|
409
|
+
|
|
410
|
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
411
|
+
local Players = game:GetService("Players")
|
|
412
|
+
|
|
413
|
+
-- Wait for modules to load
|
|
414
|
+
local Modules = ReplicatedStorage:WaitForChild("Modules")
|
|
415
|
+
local GameManager = require(Modules:WaitForChild("GameManager"))
|
|
416
|
+
|
|
417
|
+
-- Initialize game
|
|
418
|
+
local gameManager = GameManager.new()
|
|
419
|
+
gameManager:Initialize()
|
|
420
|
+
|
|
421
|
+
-- Store reference globally for other scripts
|
|
422
|
+
_G.GameManager = gameManager
|
|
423
|
+
|
|
424
|
+
-- Player handling
|
|
425
|
+
Players.PlayerAdded:Connect(function(player)
|
|
426
|
+
print("[Game] Player joined:", player.Name)
|
|
427
|
+
|
|
428
|
+
player.CharacterAdded:Connect(function(character)
|
|
429
|
+
-- Character setup
|
|
430
|
+
local humanoid = character:WaitForChild("Humanoid")
|
|
431
|
+
|
|
432
|
+
-- Apply Nice2Dev settings
|
|
433
|
+
-- humanoid.WalkSpeed = 16
|
|
434
|
+
-- humanoid.JumpPower = 50
|
|
435
|
+
end)
|
|
436
|
+
end)
|
|
437
|
+
|
|
438
|
+
Players.PlayerRemoving:Connect(function(player)
|
|
439
|
+
print("[Game] Player left:", player.Name)
|
|
440
|
+
end)
|
|
441
|
+
|
|
442
|
+
print("[Game] ${project.name} initialized successfully!")
|
|
569
443
|
`;
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
local
|
|
581
|
-
local
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
},
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
end)
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
end
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
end
|
|
668
|
-
|
|
669
|
-
|
|
444
|
+
this.addTextFile("ServerScriptService/GameInit.server.lua", initScript);
|
|
445
|
+
}
|
|
446
|
+
/* ── Client Scripts ─────────────────────────────────────────── */
|
|
447
|
+
async generateClientScripts(_project, _options) {
|
|
448
|
+
const clientController = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
449
|
+
Client Controller
|
|
450
|
+
Handles client-side game logic and input
|
|
451
|
+
]]
|
|
452
|
+
|
|
453
|
+
local Players = game:GetService("Players")
|
|
454
|
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
455
|
+
local UserInputService = game:GetService("UserInputService")
|
|
456
|
+
local RunService = game:GetService("RunService")
|
|
457
|
+
|
|
458
|
+
local LocalPlayer = Players.LocalPlayer
|
|
459
|
+
|
|
460
|
+
-- Modules
|
|
461
|
+
local Modules = ReplicatedStorage:WaitForChild("Modules")
|
|
462
|
+
local Utility = require(Modules:WaitForChild("Utility"))
|
|
463
|
+
|
|
464
|
+
-- Input State
|
|
465
|
+
local inputState = {
|
|
466
|
+
moveDirection = Vector3.new(0, 0, 0),
|
|
467
|
+
mousePosition = Vector2.new(0, 0),
|
|
468
|
+
keysDown = {},
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
-- Input Handling
|
|
472
|
+
UserInputService.InputBegan:Connect(function(input, gameProcessed)
|
|
473
|
+
if gameProcessed then return end
|
|
474
|
+
|
|
475
|
+
if input.UserInputType == Enum.UserInputType.Keyboard then
|
|
476
|
+
inputState.keysDown[input.KeyCode] = true
|
|
477
|
+
|
|
478
|
+
-- Example: Jump on space
|
|
479
|
+
if input.KeyCode == Enum.KeyCode.Space then
|
|
480
|
+
local character = LocalPlayer.Character
|
|
481
|
+
if character then
|
|
482
|
+
local humanoid = character:FindFirstChildOfClass("Humanoid")
|
|
483
|
+
if humanoid then
|
|
484
|
+
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
|
|
489
|
+
-- Left click
|
|
490
|
+
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
|
|
491
|
+
-- Right click
|
|
492
|
+
end
|
|
493
|
+
end)
|
|
494
|
+
|
|
495
|
+
UserInputService.InputEnded:Connect(function(input, gameProcessed)
|
|
496
|
+
if input.UserInputType == Enum.UserInputType.Keyboard then
|
|
497
|
+
inputState.keysDown[input.KeyCode] = nil
|
|
498
|
+
end
|
|
499
|
+
end)
|
|
500
|
+
|
|
501
|
+
-- Mouse tracking
|
|
502
|
+
UserInputService.InputChanged:Connect(function(input)
|
|
503
|
+
if input.UserInputType == Enum.UserInputType.MouseMovement then
|
|
504
|
+
inputState.mousePosition = Vector2.new(input.Position.X, input.Position.Y)
|
|
505
|
+
end
|
|
506
|
+
end)
|
|
507
|
+
|
|
508
|
+
-- Helper functions
|
|
509
|
+
local function IsKeyDown(keyCode: Enum.KeyCode): boolean
|
|
510
|
+
return inputState.keysDown[keyCode] ~= nil
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
local function GetMoveDirection(): Vector3
|
|
514
|
+
local direction = Vector3.new(0, 0, 0)
|
|
515
|
+
|
|
516
|
+
if IsKeyDown(Enum.KeyCode.W) or IsKeyDown(Enum.KeyCode.Up) then
|
|
517
|
+
direction = direction + Vector3.new(0, 0, -1)
|
|
518
|
+
end
|
|
519
|
+
if IsKeyDown(Enum.KeyCode.S) or IsKeyDown(Enum.KeyCode.Down) then
|
|
520
|
+
direction = direction + Vector3.new(0, 0, 1)
|
|
521
|
+
end
|
|
522
|
+
if IsKeyDown(Enum.KeyCode.A) or IsKeyDown(Enum.KeyCode.Left) then
|
|
523
|
+
direction = direction + Vector3.new(-1, 0, 0)
|
|
524
|
+
end
|
|
525
|
+
if IsKeyDown(Enum.KeyCode.D) or IsKeyDown(Enum.KeyCode.Right) then
|
|
526
|
+
direction = direction + Vector3.new(1, 0, 0)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
if direction.Magnitude > 0 then
|
|
530
|
+
direction = direction.Unit
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
return direction
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
-- Client update loop
|
|
537
|
+
RunService.RenderStepped:Connect(function(deltaTime)
|
|
538
|
+
inputState.moveDirection = GetMoveDirection()
|
|
539
|
+
|
|
540
|
+
-- Update client-side effects, animations, etc.
|
|
541
|
+
end)
|
|
542
|
+
|
|
543
|
+
print("[ClientController] Initialized")
|
|
670
544
|
`;
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
545
|
+
this.addTextFile(
|
|
546
|
+
"StarterPlayer/StarterPlayerScripts/ClientController.client.lua",
|
|
547
|
+
clientController
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
/* ── Server Scripts ─────────────────────────────────────────── */
|
|
551
|
+
async generateServerScripts(project, _options) {
|
|
552
|
+
const dataScript = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
553
|
+
Data Handler Script
|
|
554
|
+
Handles player data saving and loading using DataStoreService
|
|
555
|
+
]]
|
|
556
|
+
|
|
557
|
+
local DataStoreService = game:GetService("DataStoreService")
|
|
558
|
+
local Players = game:GetService("Players")
|
|
559
|
+
|
|
560
|
+
local playerDataStore = DataStoreService:GetDataStore("PlayerData_${this.projectName}")
|
|
561
|
+
|
|
562
|
+
-- Default player data
|
|
563
|
+
local defaultData = {
|
|
564
|
+
coins = 0,
|
|
565
|
+
level = 1,
|
|
566
|
+
experience = 0,
|
|
567
|
+
inventory = {},
|
|
568
|
+
settings = {
|
|
569
|
+
musicVolume = ${project.settings.audio.masterVolume},
|
|
570
|
+
sfxVolume = 1.0,
|
|
571
|
+
},
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
local playerData = {}
|
|
575
|
+
|
|
576
|
+
local function LoadPlayerData(player: Player): {[string]: any}
|
|
577
|
+
local success, data = pcall(function()
|
|
578
|
+
return playerDataStore:GetAsync("Player_" .. player.UserId)
|
|
579
|
+
end)
|
|
580
|
+
|
|
581
|
+
if success and data then
|
|
582
|
+
-- Merge with defaults for any missing keys
|
|
583
|
+
for key, value in pairs(defaultData) do
|
|
584
|
+
if data[key] == nil then
|
|
585
|
+
data[key] = value
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
return data
|
|
589
|
+
else
|
|
590
|
+
warn("[Data] Failed to load data for", player.Name, "using defaults")
|
|
591
|
+
return table.clone(defaultData)
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
local function SavePlayerData(player: Player, data: {[string]: any})
|
|
596
|
+
local success, err = pcall(function()
|
|
597
|
+
playerDataStore:SetAsync("Player_" .. player.UserId, data)
|
|
598
|
+
end)
|
|
599
|
+
|
|
600
|
+
if not success then
|
|
601
|
+
warn("[Data] Failed to save data for", player.Name, ":", err)
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
-- Player handling
|
|
606
|
+
Players.PlayerAdded:Connect(function(player)
|
|
607
|
+
playerData[player.UserId] = LoadPlayerData(player)
|
|
608
|
+
print("[Data] Loaded data for", player.Name)
|
|
609
|
+
end)
|
|
610
|
+
|
|
611
|
+
Players.PlayerRemoving:Connect(function(player)
|
|
612
|
+
if playerData[player.UserId] then
|
|
613
|
+
SavePlayerData(player, playerData[player.UserId])
|
|
614
|
+
playerData[player.UserId] = nil
|
|
615
|
+
print("[Data] Saved data for", player.Name)
|
|
616
|
+
end
|
|
617
|
+
end)
|
|
618
|
+
|
|
619
|
+
-- Auto-save every 5 minutes
|
|
620
|
+
task.spawn(function()
|
|
621
|
+
while true do
|
|
622
|
+
task.wait(300)
|
|
623
|
+
for userId, data in pairs(playerData) do
|
|
624
|
+
local player = Players:GetPlayerByUserId(userId)
|
|
625
|
+
if player then
|
|
626
|
+
SavePlayerData(player, data)
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
print("[Data] Auto-save complete")
|
|
630
|
+
end
|
|
631
|
+
end)
|
|
632
|
+
|
|
633
|
+
-- API for other scripts
|
|
634
|
+
local DataHandler = {}
|
|
635
|
+
|
|
636
|
+
function DataHandler.GetPlayerData(player: Player): {[string]: any}?
|
|
637
|
+
return playerData[player.UserId]
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
function DataHandler.SetPlayerData(player: Player, key: string, value: any)
|
|
641
|
+
if playerData[player.UserId] then
|
|
642
|
+
playerData[player.UserId][key] = value
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
return DataHandler
|
|
647
|
+
`;
|
|
648
|
+
this.addTextFile("ServerScriptService/DataHandler.server.lua", dataScript);
|
|
649
|
+
}
|
|
650
|
+
/* ── Scene Export ───────────────────────────────────────────── */
|
|
651
|
+
async exportScene(scene, project, _options) {
|
|
652
|
+
const modelXml = this.generateSceneModel(scene, project);
|
|
653
|
+
this.addTextFile(`Workspace/${scene.name}.rbxmx`, modelXml);
|
|
654
|
+
const sceneScript = this.generateSceneScript(scene);
|
|
655
|
+
this.addTextFile(`ServerScriptService/Scenes/${scene.name}.server.lua`, sceneScript);
|
|
656
|
+
}
|
|
657
|
+
generateSceneModel(scene, _project) {
|
|
658
|
+
const instances = [];
|
|
659
|
+
instances.push(`<Item class="Folder" referent="RBX_SCENE_ROOT">
|
|
660
|
+
<Properties>
|
|
661
|
+
<string name="Name">${scene.name}</string>
|
|
688
662
|
</Properties>`);
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
${instances.join('\n ')}
|
|
663
|
+
for (const entity of scene.entities) {
|
|
664
|
+
instances.push(this.generateEntityXml(entity));
|
|
665
|
+
}
|
|
666
|
+
instances.push(`</Item>`);
|
|
667
|
+
return `<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
|
|
668
|
+
<Meta name="ExplicitAutoJoints">true</Meta>
|
|
669
|
+
${instances.join("\n ")}
|
|
697
670
|
</roblox>`;
|
|
671
|
+
}
|
|
672
|
+
generateEntityXml(entity, _parentRef = "RBX_SCENE_ROOT") {
|
|
673
|
+
const pos = entity.position ?? { x: 0, y: 0 };
|
|
674
|
+
const scale = entity.scale ?? { x: 1, y: 1 };
|
|
675
|
+
const referent = `RBX_${entity.id.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
676
|
+
let instanceClass = "Part";
|
|
677
|
+
const additionalProps = "";
|
|
678
|
+
const hasCollider = entity.components.some((c) => c.type.includes("Collider"));
|
|
679
|
+
entity.components.some((c) => c.type === "sprite");
|
|
680
|
+
const hasLight = entity.components.some((c) => c.type === "light");
|
|
681
|
+
if (hasLight) {
|
|
682
|
+
instanceClass = "Part";
|
|
698
683
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
<Y>${pos.y}</Y>
|
|
718
|
-
<Z>0</Z>
|
|
719
|
-
</Vector3>
|
|
720
|
-
<Vector3 name="Size">
|
|
721
|
-
<X>${scale.x}</X>
|
|
722
|
-
<Y>${scale.y}</Y>
|
|
723
|
-
<Z>1</Z>
|
|
724
|
-
</Vector3>
|
|
725
|
-
<bool name="Anchored">${!entity.components.some((c) => c.type === 'rigidbody')}</bool>
|
|
726
|
-
<bool name="CanCollide">${hasCollider}</bool>
|
|
727
|
-
${additionalProps}
|
|
728
|
-
</Properties>
|
|
729
|
-
${this.generateComponentChildren(entity)}
|
|
684
|
+
const xml = `<Item class="${instanceClass}" referent="${referent}">
|
|
685
|
+
<Properties>
|
|
686
|
+
<string name="Name">${entity.name ?? entity.id}</string>
|
|
687
|
+
<Vector3 name="Position">
|
|
688
|
+
<X>${pos.x}</X>
|
|
689
|
+
<Y>${pos.y}</Y>
|
|
690
|
+
<Z>0</Z>
|
|
691
|
+
</Vector3>
|
|
692
|
+
<Vector3 name="Size">
|
|
693
|
+
<X>${scale.x}</X>
|
|
694
|
+
<Y>${scale.y}</Y>
|
|
695
|
+
<Z>1</Z>
|
|
696
|
+
</Vector3>
|
|
697
|
+
<bool name="Anchored">${!entity.components.some((c) => c.type === "rigidbody")}</bool>
|
|
698
|
+
<bool name="CanCollide">${hasCollider}</bool>
|
|
699
|
+
${additionalProps}
|
|
700
|
+
</Properties>
|
|
701
|
+
${this.generateComponentChildren(entity)}
|
|
730
702
|
</Item>`;
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
<Properties>
|
|
743
|
-
<Color3 name="Color">${this.hexToRobloxColor3(lightColor)}</Color3>
|
|
744
|
-
<float name="Brightness">${brightness}</float>
|
|
745
|
-
<float name="Range">${range}</float>
|
|
746
|
-
</Properties>
|
|
703
|
+
return xml;
|
|
704
|
+
}
|
|
705
|
+
generateComponentChildren(entity) {
|
|
706
|
+
const children = [];
|
|
707
|
+
for (const comp of entity.components) {
|
|
708
|
+
switch (comp.type) {
|
|
709
|
+
case "light": {
|
|
710
|
+
const lightColor = comp.properties?.["color"] ?? "#ffffff";
|
|
711
|
+
const brightness = comp.properties?.["intensity"] ?? 1;
|
|
712
|
+
const range = comp.properties?.["range"] ?? 10;
|
|
713
|
+
children.push(`<Item class="PointLight">
|
|
714
|
+
<Properties>
|
|
715
|
+
<Color3 name="Color">${this.hexToRobloxColor3(lightColor)}</Color3>
|
|
716
|
+
<float name="Brightness">${brightness}</float>
|
|
717
|
+
<float name="Range">${range}</float>
|
|
718
|
+
</Properties>
|
|
747
719
|
</Item>`);
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
<Properties>
|
|
756
|
-
<string name="Name">${comp.type}_sound</string>
|
|
757
|
-
<Content name="SoundId"><url>${soundId ??
|
|
758
|
-
<float name="Volume">${volume}</float>
|
|
759
|
-
<bool name="Looped">${loop}</bool>
|
|
760
|
-
</Properties>
|
|
761
|
-
</Item>`);
|
|
762
|
-
break;
|
|
763
|
-
}
|
|
764
|
-
case 'particleEmitter':
|
|
765
|
-
children.push(`<Item class="ParticleEmitter">
|
|
766
|
-
<Properties>
|
|
767
|
-
<string name="Name">${comp.type}_emitter</string>
|
|
768
|
-
<float name="Rate">${comp.properties?.['rate'] ?? 10}</float>
|
|
769
|
-
</Properties>
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
case "audioSource": {
|
|
723
|
+
const soundId = comp.properties?.["clip"];
|
|
724
|
+
const volume = comp.properties?.["volume"] ?? 1;
|
|
725
|
+
const loop = comp.properties?.["loop"] ?? false;
|
|
726
|
+
children.push(`<Item class="Sound">
|
|
727
|
+
<Properties>
|
|
728
|
+
<string name="Name">${comp.type}_sound</string>
|
|
729
|
+
<Content name="SoundId"><url>${soundId ?? ""}</url></Content>
|
|
730
|
+
<float name="Volume">${volume}</float>
|
|
731
|
+
<bool name="Looped">${loop}</bool>
|
|
732
|
+
</Properties>
|
|
770
733
|
</Item>`);
|
|
771
|
-
|
|
772
|
-
}
|
|
734
|
+
break;
|
|
773
735
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
736
|
+
case "particleEmitter":
|
|
737
|
+
children.push(`<Item class="ParticleEmitter">
|
|
738
|
+
<Properties>
|
|
739
|
+
<string name="Name">${comp.type}_emitter</string>
|
|
740
|
+
<float name="Rate">${comp.properties?.["rate"] ?? 10}</float>
|
|
741
|
+
</Properties>
|
|
742
|
+
</Item>`);
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
782
745
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
--
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
746
|
+
return children.join("\n ");
|
|
747
|
+
}
|
|
748
|
+
hexToRobloxColor3(hex) {
|
|
749
|
+
const h = hex.replace("#", "");
|
|
750
|
+
const r = parseInt(h.substr(0, 2), 16) / 255;
|
|
751
|
+
const g = parseInt(h.substr(2, 2), 16) / 255;
|
|
752
|
+
const b = parseInt(h.substr(4, 2), 16) / 255;
|
|
753
|
+
return `<R>${r.toFixed(6)}</R><G>${g.toFixed(6)}</G><B>${b.toFixed(6)}</B>`;
|
|
754
|
+
}
|
|
755
|
+
generateSceneScript(scene) {
|
|
756
|
+
return `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
757
|
+
Scene Script: ${scene.name}
|
|
758
|
+
Generated from Nice2Dev scene
|
|
759
|
+
]]
|
|
760
|
+
|
|
761
|
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
762
|
+
local Modules = ReplicatedStorage:WaitForChild("Modules")
|
|
763
|
+
local EntityBase = require(Modules:WaitForChild("EntityBase"))
|
|
764
|
+
local GameManager = require(Modules:WaitForChild("GameManager"))
|
|
765
|
+
|
|
766
|
+
local SceneManager = {}
|
|
767
|
+
|
|
768
|
+
-- Entity definitions for this scene
|
|
769
|
+
local entityDefinitions = {
|
|
770
|
+
${scene.entities.map(
|
|
771
|
+
(e) => ` ["${e.id}"] = {
|
|
772
|
+
name = "${e.name ?? e.id}",
|
|
773
|
+
position = Vector3.new(${e.position?.x ?? 0}, ${e.position?.y ?? 0}, 0),
|
|
774
|
+
tags = {${(e.tags ?? []).map((t) => `"${t}"`).join(", ")}},
|
|
775
|
+
},`
|
|
776
|
+
).join("\n")}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function SceneManager:Initialize()
|
|
780
|
+
-- Create entities from definitions
|
|
781
|
+
for id, def in pairs(entityDefinitions) do
|
|
782
|
+
local entity = EntityBase.new(id, def.name)
|
|
783
|
+
entity.Tags = def.tags
|
|
784
|
+
|
|
785
|
+
-- Find or create instance in workspace
|
|
786
|
+
local folder = workspace:FindFirstChild("${scene.name}")
|
|
787
|
+
if folder then
|
|
788
|
+
local instance = folder:FindFirstChild(def.name)
|
|
789
|
+
if instance then
|
|
790
|
+
entity.Instance = instance
|
|
791
|
+
end
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
-- Register with GameManager
|
|
795
|
+
if _G.GameManager then
|
|
796
|
+
_G.GameManager:RegisterEntity(id, entity)
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
entity:Start()
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
print("[Scene] ${scene.name} initialized with", #entityDefinitions, "entities")
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
function SceneManager:Cleanup()
|
|
806
|
+
for id, _ in pairs(entityDefinitions) do
|
|
807
|
+
if _G.GameManager then
|
|
808
|
+
local entity = _G.GameManager:GetEntity(id)
|
|
809
|
+
if entity then
|
|
810
|
+
entity:Destroy()
|
|
811
|
+
end
|
|
812
|
+
_G.GameManager:UnregisterEntity(id)
|
|
813
|
+
end
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
return SceneManager
|
|
846
818
|
`;
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
local
|
|
857
|
-
local
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
},
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
)
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
part.
|
|
881
|
-
part.
|
|
882
|
-
part.
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
entity
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
return ${prefab.name}Prefab
|
|
819
|
+
}
|
|
820
|
+
/* ── Prefab Export ──────────────────────────────────────────── */
|
|
821
|
+
async exportPrefab(prefab, _options) {
|
|
822
|
+
const prefabModule = `${this.useStrictMode ? "--!strict\n" : ""}--[[
|
|
823
|
+
Prefab Module: ${prefab.name}
|
|
824
|
+
Generated from Nice2Dev prefab
|
|
825
|
+
]]
|
|
826
|
+
|
|
827
|
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
828
|
+
local Modules = ReplicatedStorage:WaitForChild("Modules")
|
|
829
|
+
local EntityBase = require(Modules:WaitForChild("EntityBase"))
|
|
830
|
+
|
|
831
|
+
local ${prefab.name}Prefab = {}
|
|
832
|
+
|
|
833
|
+
-- Prefab definition
|
|
834
|
+
local prefabDef = {
|
|
835
|
+
name = "${prefab.entity.name ?? prefab.name}",
|
|
836
|
+
components = {
|
|
837
|
+
${prefab.entity.components.map((c) => ` { type = "${c.type}", properties = ${this.luaTableFromObject(c.properties ?? {})} },`).join("\n")}
|
|
838
|
+
},
|
|
839
|
+
tags = {${(prefab.entity.tags ?? []).map((t) => `"${t}"`).join(", ")}},
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
function ${prefab.name}Prefab.Spawn(position: Vector3, parent: Instance?): any
|
|
843
|
+
local entity = EntityBase.new(
|
|
844
|
+
game:GetService("HttpService"):GenerateGUID(false),
|
|
845
|
+
prefabDef.name
|
|
846
|
+
)
|
|
847
|
+
entity.Tags = table.clone(prefabDef.tags)
|
|
848
|
+
|
|
849
|
+
-- Create instance
|
|
850
|
+
local part = Instance.new("Part")
|
|
851
|
+
part.Name = prefabDef.name
|
|
852
|
+
part.Position = position
|
|
853
|
+
part.Anchored = true
|
|
854
|
+
part.Parent = parent or workspace
|
|
855
|
+
|
|
856
|
+
entity.Instance = part
|
|
857
|
+
|
|
858
|
+
-- Apply components
|
|
859
|
+
for _, comp in ipairs(prefabDef.components) do
|
|
860
|
+
-- Component setup based on type
|
|
861
|
+
if comp.type == "light" then
|
|
862
|
+
local light = Instance.new("PointLight")
|
|
863
|
+
light.Parent = part
|
|
864
|
+
elseif comp.type == "audioSource" then
|
|
865
|
+
local sound = Instance.new("Sound")
|
|
866
|
+
sound.Parent = part
|
|
867
|
+
end
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
-- Register with GameManager
|
|
871
|
+
if _G.GameManager then
|
|
872
|
+
_G.GameManager:RegisterEntity(entity.Id, entity)
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
entity:Start()
|
|
876
|
+
return entity
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
return ${prefab.name}Prefab
|
|
909
880
|
`;
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}
|
|
933
|
-
return `${key} = ${luaValue}`;
|
|
934
|
-
});
|
|
935
|
-
return `{ ${entries.join(', ')} }`;
|
|
936
|
-
}
|
|
881
|
+
this.addTextFile(`ReplicatedStorage/Prefabs/${prefab.name}.lua`, prefabModule);
|
|
882
|
+
}
|
|
883
|
+
luaTableFromObject(obj) {
|
|
884
|
+
const entries = Object.entries(obj).map(([key, value]) => {
|
|
885
|
+
let luaValue;
|
|
886
|
+
if (typeof value === "string") {
|
|
887
|
+
luaValue = `"${value}"`;
|
|
888
|
+
} else if (typeof value === "boolean") {
|
|
889
|
+
luaValue = value ? "true" : "false";
|
|
890
|
+
} else if (typeof value === "number") {
|
|
891
|
+
luaValue = String(value);
|
|
892
|
+
} else if (value === null || value === void 0) {
|
|
893
|
+
luaValue = "nil";
|
|
894
|
+
} else if (typeof value === "object") {
|
|
895
|
+
luaValue = this.luaTableFromObject(value);
|
|
896
|
+
} else {
|
|
897
|
+
luaValue = String(value);
|
|
898
|
+
}
|
|
899
|
+
return `${key} = ${luaValue}`;
|
|
900
|
+
});
|
|
901
|
+
return `{ ${entries.join(", ")} }`;
|
|
902
|
+
}
|
|
937
903
|
}
|
|
938
|
-
/* ── Factory ──────────────────────────────────────────────────── */
|
|
939
904
|
function createRobloxExporter() {
|
|
940
|
-
|
|
905
|
+
return new RobloxExporter();
|
|
941
906
|
}
|
|
942
|
-
|
|
943
907
|
exports.RobloxExporter = RobloxExporter;
|
|
944
908
|
exports.createRobloxExporter = createRobloxExporter;
|