import { create } from 'zustand'; export interface FileNode { id: string; name: string; type: 'file' | 'folder'; path: string; children?: FileNode[]; platform?: 'roblox' | 'web' | 'mobile' | 'desktop' | 'shared'; content?: string; } export interface OpenFile { id: string; name: string; path: string; content: string; language: string; isDirty: boolean; } interface EditorStore { files: FileNode[]; openFiles: OpenFile[]; activeFileId: string | null; isSaving: boolean; setFiles: (files: FileNode[]) => void; openFile: (file: FileNode) => void; closeFile: (fileId: string) => void; setActiveFile: (fileId: string) => void; updateFileContent: (fileId: string, content: string) => void; saveFile: (fileId: string) => void; saveAllFiles: () => void; moveFile: (fileId: string, targetFolderId: string) => void; } export const useEditorStore = create((set, get) => ({ files: [ { id: 'roblox', name: 'roblox', type: 'folder', path: '/roblox', platform: 'roblox', children: [ { id: 'roblox-main', name: 'main.lua', type: 'file', path: '/roblox/main.lua', platform: 'roblox', content: '-- Roblox Main Script\nprint("Hello from Roblox!")\n\n-- Player joined event\ngame.Players.PlayerAdded:Connect(function(player)\n print(player.Name .. " joined the game!")\nend)' }, { id: 'roblox-controller', name: 'player-controller.lua', type: 'file', path: '/roblox/player-controller.lua', platform: 'roblox', content: '-- Player Controller\nlocal UserInputService = game:GetService("UserInputService")\n\nlocal function onInput(input, gameProcessed)\n if gameProcessed then return end\n -- Handle input\nend\n\nUserInputService.InputBegan:Connect(onInput)' }, { id: 'roblox-datastore', name: 'datastore.lua', type: 'file', path: '/roblox/datastore.lua', platform: 'roblox', content: '-- DataStore Manager\nlocal DataStoreService = game:GetService("DataStoreService")\nlocal playerData = DataStoreService:GetDataStore("PlayerData")\n\nlocal function savePlayerData(player, data)\n -- Save data logic\nend' }, ], }, { id: 'web', name: 'web', type: 'folder', path: '/web', platform: 'web', children: [ { id: 'web-index', name: 'index.html', type: 'file', path: '/web/index.html', platform: 'web', content: '\n\n\n AeThex Game\n \n\n\n \n \n\n' }, { id: 'web-game', name: 'game.js', type: 'file', path: '/web/game.js', platform: 'web', content: '// Web Game Entry Point\nconst canvas = document.getElementById("game-canvas");\nconst ctx = canvas.getContext("2d");\n\nfunction gameLoop() {\n // Update game state\n // Render game\n requestAnimationFrame(gameLoop);\n}\n\ngameLoop();' }, { id: 'web-style', name: 'style.css', type: 'file', path: '/web/style.css', platform: 'web', content: 'body {\n margin: 0;\n padding: 0;\n overflow: hidden;\n background: #000;\n}\n\n#game-canvas {\n display: block;\n width: 100%;\n height: 100vh;\n}' }, ], }, { id: 'mobile', name: 'mobile', type: 'folder', path: '/mobile', platform: 'mobile', children: [ { id: 'mobile-app', name: 'App.tsx', type: 'file', path: '/mobile/App.tsx', platform: 'mobile', content: 'import React from "react";\nimport { GameScreen } from "./GameScreen";\n\nexport default function App() {\n return ;\n}' }, { id: 'mobile-game', name: 'GameScreen.tsx', type: 'file', path: '/mobile/GameScreen.tsx', platform: 'mobile', content: 'import React from "react";\nimport { View, Text, StyleSheet } from "react-native";\n\nexport function GameScreen() {\n return (\n \n Mobile Game\n \n );\n}\n\nconst styles = StyleSheet.create({\n container: { flex: 1, justifyContent: "center", alignItems: "center" },\n});' }, { id: 'mobile-config', name: 'config.json', type: 'file', path: '/mobile/config.json', platform: 'mobile', content: '{\n "name": "AeThexGame",\n "displayName": "AeThex Game",\n "version": "1.0.0",\n "platforms": ["ios", "android"]\n}' }, ], }, { id: 'desktop', name: 'desktop', type: 'folder', path: '/desktop', platform: 'desktop', children: [ { id: 'desktop-main', name: 'main.js', type: 'file', path: '/desktop/main.js', platform: 'desktop', content: '// Electron Main Process\nconst { app, BrowserWindow } = require("electron");\n\nfunction createWindow() {\n const win = new BrowserWindow({\n width: 1280,\n height: 720,\n webPreferences: {\n preload: __dirname + "/preload.js"\n }\n });\n win.loadFile("index.html");\n}\n\napp.whenReady().then(createWindow);' }, { id: 'desktop-preload', name: 'preload.js', type: 'file', path: '/desktop/preload.js', platform: 'desktop', content: '// Electron Preload Script\nconst { contextBridge } = require("electron");\n\ncontextBridge.exposeInMainWorld("electronAPI", {\n platform: "desktop",\n version: "1.0.0"\n});' }, ], }, { id: 'shared', name: 'shared', type: 'folder', path: '/shared', platform: 'shared', children: [ { id: 'shared-nexus', name: 'nexus-engine.ts', type: 'file', path: '/shared/nexus-engine.ts', platform: 'shared', content: '// Nexus Engine - Cross-Platform State Sync\nexport class NexusEngine {\n private state: Map = new Map();\n private listeners: Set = new Set();\n\n setState(key: string, value: any) {\n this.state.set(key, value);\n this.broadcast(key, value);\n }\n\n getState(key: string) {\n return this.state.get(key);\n }\n\n private broadcast(key: string, value: any) {\n this.listeners.forEach(listener => listener(key, value));\n }\n}' }, { id: 'shared-passport', name: 'passport-auth.ts', type: 'file', path: '/shared/passport-auth.ts', platform: 'shared', content: '// Passport - Unified Authentication\nexport class PassportAuth {\n private token: string | null = null;\n\n async login(username: string, password: string) {\n // Mock login\n this.token = "mock-token-" + username;\n return { success: true, token: this.token };\n }\n\n async logout() {\n this.token = null;\n }\n\n isAuthenticated() {\n return this.token !== null;\n }\n}' }, { id: 'shared-config', name: 'gameforge-config.json', type: 'file', path: '/shared/gameforge-config.json', platform: 'shared', content: '{\n "gameforge": {\n "antiCheat": {\n "enabled": true,\n "serverAuthoritative": true\n },\n "rules": [\n {\n "type": "speed-check",\n "maxSpeed": 100\n },\n {\n "type": "position-validation",\n "enabled": true\n }\n ]\n }\n}' }, ], }, { id: 'readme', name: 'README.md', type: 'file', path: '/README.md', content: '# AeThex Studio Project\n\nThis is a cross-platform game project built with AeThex Studio.\n\n## Platforms\n\n- **Roblox**: Multiplayer game experience\n- **Web**: Browser-based version\n- **Mobile**: iOS & Android apps\n- **Desktop**: Native Windows/Mac/Linux\n\n## Features\n\n- Nexus Engine for real-time state synchronization\n- Passport authentication for unified identity\n- GameForge anti-cheat protection\n\n## Getting Started\n\n1. Select a file from the explorer\n2. Edit your code\n3. Click "Run All Platforms" to test\n4. Deploy when ready!\n', }, ], openFiles: [], activeFileId: null, isSaving: false, setFiles: (files) => set({ files }), openFile: (file) => { const { openFiles } = get(); if (openFiles.find(f => f.id === file.id)) { set({ activeFileId: file.id }); return; } const language = file.name.endsWith('.lua') ? 'lua' : file.name.endsWith('.ts') || file.name.endsWith('.tsx') ? 'typescript' : file.name.endsWith('.js') || file.name.endsWith('.jsx') ? 'javascript' : file.name.endsWith('.html') ? 'html' : file.name.endsWith('.css') ? 'css' : file.name.endsWith('.json') ? 'json' : file.name.endsWith('.md') ? 'markdown' : 'plaintext'; const newFile: OpenFile = { id: file.id, name: file.name, path: file.path, content: file.content || '', language, isDirty: false, }; set({ openFiles: [...openFiles, newFile], activeFileId: file.id, }); }, closeFile: (fileId) => { const { openFiles, activeFileId } = get(); const newOpenFiles = openFiles.filter(f => f.id !== fileId); const newActiveId = activeFileId === fileId ? (newOpenFiles.length > 0 ? newOpenFiles[newOpenFiles.length - 1].id : null) : activeFileId; set({ openFiles: newOpenFiles, activeFileId: newActiveId, }); }, setActiveFile: (fileId) => set({ activeFileId: fileId }), updateFileContent: (fileId, content) => { const { openFiles } = get(); set({ openFiles: openFiles.map(f => f.id === fileId ? { ...f, content, isDirty: true } : f ), }); }, saveFile: (fileId) => { const { openFiles } = get(); set({ isSaving: true }); // Simulate save setTimeout(() => { set({ openFiles: openFiles.map(f => f.id === fileId ? { ...f, isDirty: false } : f ), isSaving: false, }); }, 500); }, saveAllFiles: () => { set({ isSaving: true }); setTimeout(() => { set({ openFiles: get().openFiles.map(f => ({ ...f, isDirty: false })), isSaving: false, }); }, 500); }, moveFile: (fileId: string, targetFolderId: string) => { const { files } = get(); // Helper to find and remove a file from tree const findAndRemove = (nodes: FileNode[], id: string): { nodes: FileNode[]; removed: FileNode | null } => { let removed: FileNode | null = null; const newNodes = nodes.filter(n => { if (n.id === id) { removed = n; return false; } return true; }).map(n => { if (n.children && !removed) { const result = findAndRemove(n.children, id); removed = result.removed; return { ...n, children: result.nodes }; } return n; }); return { nodes: newNodes, removed }; }; // Helper to add file to target folder const addToFolder = (nodes: FileNode[], folderId: string, file: FileNode): FileNode[] => { return nodes.map(n => { if (n.id === folderId && n.type === 'folder') { return { ...n, children: [...(n.children || []), file] }; } if (n.children) { return { ...n, children: addToFolder(n.children, folderId, file) }; } return n; }); }; const { nodes: afterRemove, removed } = findAndRemove(files, fileId); if (removed) { const newFiles = addToFolder(afterRemove, targetFolderId, removed); set({ files: newFiles }); } }, }));