algorembrant commited on
Commit
0712d5f
·
verified ·
1 Parent(s): 9d2b1f3

Upload 88 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. LICENSE +21 -0
  2. STRUCTURE.md +101 -0
  3. TECHSTACK.md +12 -0
  4. aftman.toml +7 -0
  5. default.project.json +36 -0
  6. mcp.json +10 -0
  7. roblox-studio-antigravity-mcp-guide.md +74 -0
  8. robloxstudio-mcp-system-mechanics.md +78 -0
  9. src/ReplicatedStorage/Events/ChopEvent.model.json +3 -0
  10. src/ReplicatedStorage/Events/ClaimPlot.model.json +3 -0
  11. src/ReplicatedStorage/Events/CraftEvent.model.json +3 -0
  12. src/ReplicatedStorage/Events/DialogueEvent.model.json +3 -0
  13. src/ReplicatedStorage/Events/DragEvent.model.json +3 -0
  14. src/ReplicatedStorage/Events/DropEvent.model.json +3 -0
  15. src/ReplicatedStorage/Events/EquipToolEvent.model.json +3 -0
  16. src/ReplicatedStorage/Events/FillBlueprintEvent.model.json +3 -0
  17. src/ReplicatedStorage/Events/MarketUpdateEvent.model.json +3 -0
  18. src/ReplicatedStorage/Events/NotificationEvent.model.json +3 -0
  19. src/ReplicatedStorage/Events/PlaceBlueprintEvent.model.json +3 -0
  20. src/ReplicatedStorage/Events/PurchaseEvent.model.json +3 -0
  21. src/ReplicatedStorage/Events/QuestUpdateEvent.model.json +3 -0
  22. src/ReplicatedStorage/Events/SettingsEvent.model.json +3 -0
  23. src/ReplicatedStorage/Events/ShopEvent.model.json +3 -0
  24. src/ReplicatedStorage/Events/SoundEvent.model.json +3 -0
  25. src/ReplicatedStorage/Events/WireConnectEvent.model.json +3 -0
  26. src/ReplicatedStorage/Shared/AutomationConfig.lua +20 -0
  27. src/ReplicatedStorage/Shared/BiomeConfig.lua +105 -0
  28. src/ReplicatedStorage/Shared/BuildingConfig.lua +98 -0
  29. src/ReplicatedStorage/Shared/ChoppingConfig.lua +115 -0
  30. src/ReplicatedStorage/Shared/Constants.lua +63 -0
  31. src/ReplicatedStorage/Shared/CraftingConfig.lua +74 -0
  32. src/ReplicatedStorage/Shared/DraggingConfig.lua +15 -0
  33. src/ReplicatedStorage/Shared/EconomyConfig.lua +40 -0
  34. src/ReplicatedStorage/Shared/ExplorationConfig.lua +42 -0
  35. src/ReplicatedStorage/Shared/GameConfig.lua +57 -0
  36. src/ReplicatedStorage/Shared/MutationConfig.lua +40 -0
  37. src/ReplicatedStorage/Shared/NPCConfig.lua +86 -0
  38. src/ReplicatedStorage/Shared/PlotConfig.lua +10 -0
  39. src/ReplicatedStorage/Shared/QuestConfig.lua +107 -0
  40. src/ReplicatedStorage/Shared/ShopConfig.lua +112 -0
  41. src/ReplicatedStorage/Shared/SoundConfig.lua +39 -0
  42. src/ReplicatedStorage/Shared/TreeModelConfig.lua +119 -0
  43. src/ReplicatedStorage/Shared/Utility.lua +85 -0
  44. src/ReplicatedStorage/Shared/VehicleConfig.lua +14 -0
  45. src/ReplicatedStorage/Shared/WeatherConfig.lua +17 -0
  46. src/ReplicatedStorage/Shared/WireLogicConfig.lua +14 -0
  47. src/ServerScriptService/AchievementManager.server.lua +82 -0
  48. src/ServerScriptService/AntiCheatManager.server.lua +73 -0
  49. src/ServerScriptService/BiomeGeneratorManager.server.lua +195 -0
  50. src/ServerScriptService/ConstructionManager.server.lua +88 -0
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 callmerem
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
STRUCTURE.md ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Project Structure
2
+
3
+ ```text
4
+ TimberWoods/
5
+ ├── references/
6
+ ├── src/
7
+ │ ├── ReplicatedStorage/
8
+ │ │ ├── Events/
9
+ │ │ │ ├── ChopEvent.model.json
10
+ │ │ │ ├── ClaimPlot.model.json
11
+ │ │ │ ├── CraftEvent.model.json
12
+ │ │ │ ├── DialogueEvent.model.json
13
+ │ │ │ ├── DragEvent.model.json
14
+ │ │ │ ├── DropEvent.model.json
15
+ │ │ │ ├── EquipToolEvent.model.json
16
+ │ │ │ ├── FillBlueprintEvent.model.json
17
+ │ │ │ ├── MarketUpdateEvent.model.json
18
+ │ │ │ ├── NotificationEvent.model.json
19
+ │ │ │ ├── PlaceBlueprintEvent.model.json
20
+ │ │ │ ├── PurchaseEvent.model.json
21
+ │ │ │ ├── QuestUpdateEvent.model.json
22
+ │ │ │ ├── SettingsEvent.model.json
23
+ │ │ │ ├── ShopEvent.model.json
24
+ │ │ │ ├── SoundEvent.model.json
25
+ │ │ │ └── WireConnectEvent.model.json
26
+ │ │ └── Shared/
27
+ │ │ ├── AutomationConfig.lua
28
+ │ │ ├── BiomeConfig.lua
29
+ │ │ ├── BuildingConfig.lua
30
+ │ │ ├── ChoppingConfig.lua
31
+ │ │ ├── Constants.lua
32
+ │ │ ├── CraftingConfig.lua
33
+ │ │ ├── DraggingConfig.lua
34
+ │ │ ├── EconomyConfig.lua
35
+ │ │ ├── ExplorationConfig.lua
36
+ │ │ ├── GameConfig.lua
37
+ │ │ ├── MutationConfig.lua
38
+ │ │ ├── NPCConfig.lua
39
+ │ │ ├── PlotConfig.lua
40
+ │ │ ├── QuestConfig.lua
41
+ │ │ ├── ShopConfig.lua
42
+ │ │ ├── SoundConfig.lua
43
+ │ │ ├── TreeModelConfig.lua
44
+ │ │ ├── Utility.lua
45
+ │ │ ├── VehicleConfig.lua
46
+ │ │ ├── WeatherConfig.lua
47
+ │ │ └── WireLogicConfig.lua
48
+ │ ├── ServerScriptService/
49
+ │ │ ├── AchievementManager.server.lua
50
+ │ │ ├── AntiCheatManager.server.lua
51
+ │ │ ├── BiomeGeneratorManager.server.lua
52
+ │ │ ├── ConstructionManager.server.lua
53
+ │ │ ├── CraftingManager.server.lua
54
+ │ │ ├── DatastoreManager.server.lua
55
+ │ │ ├── DayNightManager.server.lua
56
+ │ │ ├── DragManager.server.lua
57
+ │ │ ├── DroneAutomationManager.server.lua
58
+ │ │ ├── EnvironmentalPuzzleManager.server.lua
59
+ │ │ ├── InventoryManager.server.lua
60
+ │ │ ├── LeaderboardManager.server.lua
61
+ │ │ ├── MapManager.server.lua
62
+ │ │ ├── MarketManager.server.lua
63
+ │ │ ├── MutationManager.server.lua
64
+ │ │ ├── NPCManager.server.lua
65
+ │ │ ├── PlayerSetupManager.server.lua
66
+ │ │ ├── PlotManager.server.lua
67
+ │ │ ├── QuestManager.server.lua
68
+ │ │ ├── RespawnManager.server.lua
69
+ │ │ ├── SawmillManager.server.lua
70
+ │ │ ├── ShopManager.server.lua
71
+ │ │ ├── SoundscapeManager.server.lua
72
+ │ │ ├── TreeManager.server.lua
73
+ │ │ ├── TreeSpawnerManager.server.lua
74
+ │ │ ├── VehicleLogisticsManager.server.lua
75
+ │ │ ├── WeatherManager.server.lua
76
+ │ │ └── WireLogicManager.server.lua
77
+ │ ├── StarterGui/
78
+ │ │ ├── CraftingGUI.client.lua
79
+ │ │ ├── DialogueGUI.client.lua
80
+ │ │ ├── InventoryGUI.client.lua
81
+ │ │ ├── MainHUD.client.lua
82
+ │ │ ├── MarketGUI.client.lua
83
+ │ │ ├── QuestGUI.client.lua
84
+ │ │ ├── SettingsGUI.client.lua
85
+ │ │ └── ShopGUI.client.lua
86
+ │ └── StarterPlayer/
87
+ │ └── StarterCharacterScripts/
88
+ │ ├── AxeController.client.lua
89
+ │ ├── BuildController.client.lua
90
+ │ ├── DragController.client.lua
91
+ │ └── SoundController.client.lua
92
+ ├── aftman.toml
93
+ ├── default.project.json
94
+ ├── LICENSE
95
+ ├── mcp.json
96
+ ├── roblox-studio-antigravity-mcp-guide.md
97
+ ├── robloxstudio-mcp-system-mechanics.md
98
+ ├── studio-rust-mcp-server-system-mechanics.md
99
+ ├── studio_setup_guide.md
100
+ └── TECHSTACK.md
101
+ ```
TECHSTACK.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Techstack
2
+
3
+ Audit of **TimberWoods** project files (excluding environment and cache):
4
+
5
+ | File Type | Count | Size (KB) |
6
+ | :--- | :--- | :--- |
7
+ | Lua (.lua) | 61 | 212.2 |
8
+ | JSON (.json) | 19 | 1.8 |
9
+ | Markdown (.md) | 4 | 17.8 |
10
+ | (no extension) | 1 | 1.1 |
11
+ | TOML (.toml) | 1 | 0.3 |
12
+ | **Total** | **86** | **233.1** |
aftman.toml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # This file lists tools managed by Aftman, a cross-platform toolchain manager.
2
+ # For more information, see https://github.com/LPGhatguy/aftman
3
+
4
+ # To add a new tool, add an entry to this table.
5
+ [tools]
6
+ rojo = "rojo-rbx/rojo@7.7.0-rc.1"
7
+ # rojo = "rojo-rbx/rojo@6.2.0"
default.project.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "TimberboundExpeditions",
3
+ "tree": {
4
+ "$className": "DataModel",
5
+ "ReplicatedStorage": {
6
+ "$className": "ReplicatedStorage",
7
+ "Shared": {
8
+ "$path": "src/ReplicatedStorage/Shared"
9
+ },
10
+ "Events": {
11
+ "$path": "src/ReplicatedStorage/Events"
12
+ }
13
+ },
14
+ "ServerScriptService": {
15
+ "$className": "ServerScriptService",
16
+ "TimberboundServer": {
17
+ "$path": "src/ServerScriptService"
18
+ }
19
+ },
20
+ "StarterPlayer": {
21
+ "$className": "StarterPlayer",
22
+ "StarterCharacterScripts": {
23
+ "$className": "StarterCharacterScripts",
24
+ "TimberboundClient": {
25
+ "$path": "src/StarterPlayer/StarterCharacterScripts"
26
+ }
27
+ }
28
+ },
29
+ "StarterGui": {
30
+ "$className": "StarterGui",
31
+ "TimberboundGUI": {
32
+ "$path": "src/StarterGui"
33
+ }
34
+ }
35
+ }
36
+ }
mcp.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "mcpServers": {
3
+ "Roblox Studio": {
4
+ "command": "C:\\Users\\User\\Desktop\\VSCode2\\RobloxStudio-MCP-GoogleAntigravity\\references\\studio-rust-mcp-server-main\\target\\release\\rbx-studio-mcp.exe",
5
+ "args": [
6
+ "--stdio"
7
+ ]
8
+ }
9
+ }
10
+ }
roblox-studio-antigravity-mcp-guide.md ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Integrating Google Antigravity with Roblox Studio via Rust MCP
2
+
3
+ This guide outlines exactly how to connect the Google Antigravity system (running within VS Code) natively to your Roblox Studio instance utilizing the high-performance **Rust Model Context Protocol (MCP)** implementation.
4
+
5
+ ---
6
+
7
+ ## Step 1: Prepare the Rust Environment
8
+
9
+ The `studio-rust-mcp-server-main` reference must first be built into a local binary.
10
+
11
+ 1. Open your terminal inside the `studio-rust-mcp-server-main` repository directory.
12
+ 2. Ensure you have Rust and Cargo installed via rustup.
13
+ 3. Build the server for release:
14
+ ```bash
15
+ cargo build --release
16
+ ```
17
+ 4. This will output a binary executable located at `target\release\rbx-studio-mcp.exe`.
18
+
19
+ ## Step 2: Configure Google Antigravity (VS Code)
20
+
21
+ Google Antigravity leverages a configuration file named `mcp.json` inside your VS Code user data directory to identify connected AI bridging servers.
22
+
23
+ 1. Navigate to your VS Code data folder. On Windows, this is typically located at:
24
+ `C:\Users\User\AppData\Roaming\Code\User\mcp.json`
25
+ *(If the file does not exist, create it).*
26
+ 2. Add the `Roblox Studio` entry to the `mcpServers` object, directing it to your compiled executable and passing the required `--stdio` flag. The file should look like this:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "Roblox Studio": {
32
+ "command": "C:\\Users\\User\\Desktop\\VSCode2\\RobloxStudio-MCP-GoogleAntigravity\\references\\studio-rust-mcp-server-main\\target\\release\\rbx-studio-mcp.exe",
33
+ "args": [
34
+ "--stdio"
35
+ ]
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Step 3: Install the Studio Component Plugin
42
+
43
+ The Rust MCP server utilizes a native Roblox Studio plugin (`MCPStudioPlugin.rbxm`) to communicate over local ports via long polling. The compiled server binary can install this plugin automatically.
44
+
45
+ 1. Run the `.exe` directly **without any arguments** from your command line:
46
+ ```bash
47
+ .\target\release\rbx-studio-mcp.exe
48
+ ```
49
+ 2. The installer will automatically extract and inject the plugin directly into your local Roblox plugins directory (`%LOCALAPPDATA%\Roblox\Plugins`).
50
+
51
+ ## Step 4: Finalizing the Integration
52
+
53
+ You must make both systems aware of the new bridging connections.
54
+
55
+ 1. **Reload VS Code**: Because you just created/modified `mcp.json`, the Antigravity system hasn't loaded it yet. Run the VS Code command `Developer: Reload Window` (Ctrl+Shift+P) or simply restart VS Code entirely.
56
+ 2. **Restart Roblox Studio**: Open any local place or project file to load your plugins.
57
+ 3. **Activate the Plugin**: In the Studio `Plugins` toolbar, click the MCP icon to toggle it ON. Look at your Studio `Output` window—you should see the message:
58
+ > `"The MCP Studio plugin is ready for prompts."`
59
+
60
+ ---
61
+
62
+ ## Step 5: Test the Workspace Link!
63
+
64
+ The setup is complete! Since Google Antigravity relies on an internal network of autonomous tools (and doesn't require jumping through an external Claude/Cursor GUI), you can simply begin prompting directly in the Antigravity chat:
65
+
66
+ - *"List the child elements of my Workspace."*
67
+ - *"Create a red part at the world spawn."*
68
+ - *"Find and report any LocalScripts currently running in ReplicatedStorage."*
69
+
70
+ Antigravity will instantly pipe instructions sequentially through `rbx-studio-mcp.exe`, execute natively inside Roblox Studio's DataModel, and retrieve responses securely back into your agent interface.
71
+
72
+ # others
73
+
74
+ cat C:\Users\User\AppData\Roaming\Code\User\mcp.json
robloxstudio-mcp-system-mechanics.md ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NOTE: This is from 'C:\Users\User\Desktop\VSCode2\RobloxStudio-MCP-GoogleAntigravity\references\robloxstudio-mcp-main'.
2
+
3
+ # Roblox Studio MCP Server (Node.js/TypeScript) System Mechanics
4
+
5
+ This document provides a detailed breakdown of the system architecture and mechanics for the `robloxstudio-mcp` project, which facilitates communication between an LLM Client (like Claude or Cursor) and Roblox Studio.
6
+
7
+ ## Architecture Diagram
8
+
9
+ Below is a detailed Mermaid sequence diagram illustrating the lifecycle of a tool request in this environment.
10
+
11
+ ```mermaid
12
+ sequenceDiagram
13
+ participant LLM as LLM Client (Claude/Cursor)
14
+ participant MCP as Node.js MCP Server (stdio)
15
+ participant Bridge as BridgeService (Memory)
16
+ participant HTTP as Express HTTP Server (:port)
17
+ participant Plugin as Roblox Studio Plugin (Luau)
18
+
19
+ note over LLM,Plugin: 1. Setup Phase
20
+ HTTP-->>Plugin: Setup Endpoints (/health, /poll, /response)
21
+ Plugin->>HTTP: POST /ready (Initialize Connection)
22
+ HTTP->>Bridge: bridge.clearAllPendingRequests()
23
+
24
+ note over LLM,Plugin: 2. Long Polling Loop
25
+ loop Every few seconds or immediately after a response
26
+ Plugin->>HTTP: GET /poll
27
+ HTTP->>Bridge: getPendingRequest()
28
+ alt No pending request
29
+ HTTP-->>Plugin: empty response (after delay/timeout)
30
+ else Has pending request
31
+ HTTP-->>Plugin: JSON { request, requestId }
32
+ end
33
+ end
34
+
35
+ note over LLM,Plugin: 3. Tool Execution Lifecycle
36
+ LLM->>MCP: CallTool (e.g., get_file_tree)
37
+ MCP->>Bridge: sendRequest(endpoint, data)
38
+ Bridge->>Bridge: generate UUID & store in pendingRequests Map
39
+
40
+ note right of HTTP: The next long poll from Plugin hits...
41
+ Plugin->>HTTP: GET /poll
42
+ HTTP->>Bridge: getPendingRequest()
43
+ Bridge-->>HTTP: oldest pending request
44
+ HTTP-->>Plugin: Return Request Payload (requestId, tool data)
45
+
46
+ note over Plugin: Evaluates request & interacts with Roblox DataModel
47
+
48
+ Plugin->>HTTP: POST /response { requestId, response, error }
49
+ HTTP->>Bridge: resolveRequest(requestId, response)
50
+ Bridge->>Bridge: Match UUID, trigger promise resolve
51
+ Bridge-->>MCP: Return result
52
+ MCP-->>LLM: Return CallToolResult
53
+ ```
54
+
55
+ ## Detailed Discussion
56
+
57
+ ### Components Overview
58
+
59
+ 1. **MCP Server over stdio (`src/index.ts`)**:
60
+ The core entry point utilizes the `@modelcontextprotocol/sdk` to expose Roblox Studio capabilities to AI assistants via Standard AI standard input/output streams (`stdio`). It initializes various available tools (like `get_file_tree`, `search_files`, `edit_script_lines`, etc.) and maps them to functions in `RobloxStudioTools`.
61
+
62
+ 2. **BridgeService (`src/bridge-service.ts`)**:
63
+ Since standard LLMs cannot execute HTTP requests directly into the Roblox Studio execution context, a "Bridge" is required. The `BridgeService` stores requests originating from the LLM in memory utilizing a `Map<string, PendingRequest>`. It assigns a `uuidv4` identifier to each request, resolving or rejecting Javascript Promises when Roblox Studio responds or naturally timing out after 30 seconds.
64
+
65
+ 3. **Express HTTP Server (`src/http-server.ts`)**:
66
+ Exposed locally, this server creates standard REST API endpoints mapping to the bridge context:
67
+ - `/ready` and `/disconnect`: Manage lifecycle awareness for the connected plugin.
68
+ - `/poll`: The crucial endpoint for the long-polling architecture. The Roblox Studio plugin continuously sends GET requests here. If a request exists, it returns immediately; otherwise, it waits/cycles to keep the network open without overwhelming the LLM client.
69
+ - `/response`: Where the plugin submits the results of executed queries natively run inside Studio.
70
+ - Various `/mcp/*` endpoints exist natively simulating the tools routing.
71
+
72
+ 4. **Roblox Studio Plugin (`studio-plugin/src/...`)**:
73
+ Written in Luau. Because Roblox restricts incoming connections for security, the plugin utilizes `HttpService` to make outgoing requests to the local Express server. It intercepts the HTTP Polling results, runs internal Studio SDK functions (e.g., getting hierarchical Place structures, updating script source code), and uses `/response` to fire the feedback back up the chain.
74
+
75
+ ### Core Mechanics
76
+
77
+ - **Asynchronous Execution Gap Check**: The Node.js application is cleanly divided between the immediate `stdio` processing required by AI environments and the delayed networking constraints of `HttpService` in Roblox. The Promise architecture in the `BridgeService` forces the LLM to patiently await a complete trip through the local REST API and back.
78
+ - **Robust Toolset**: Uniquely among implementations, the TS-based server opts to fully define over 30 distinct granular tools (e.g., `insert_script_lines`, `mass_create_objects`) rather than primarily depending on evaluating raw Luau injected as strings. This gives the AI safer, strictly structured constraints to work within instead of writing custom engine scripts consistently over REST.
src/ReplicatedStorage/Events/ChopEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/ClaimPlot.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/CraftEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/DialogueEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/DragEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/DropEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/EquipToolEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/FillBlueprintEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/MarketUpdateEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/NotificationEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/PlaceBlueprintEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/PurchaseEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/QuestUpdateEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/SettingsEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/ShopEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/SoundEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Events/WireConnectEvent.model.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "ClassName": "RemoteEvent"
3
+ }
src/ReplicatedStorage/Shared/AutomationConfig.lua ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/AutomationConfig.lua
2
+
3
+ local AutomationConfig = {
4
+ Drones = {
5
+ BasicDrone = {
6
+ Speed = 20,
7
+ MaxCarryWeight = 50, -- Volume limit
8
+ EnergyCapacity = 100,
9
+ EnergyDrainPerStud = 0.1
10
+ },
11
+ AdvancedDrone = {
12
+ Speed = 40,
13
+ MaxCarryWeight = 150,
14
+ EnergyCapacity = 300,
15
+ EnergyDrainPerStud = 0.05
16
+ }
17
+ }
18
+ }
19
+
20
+ return AutomationConfig
src/ReplicatedStorage/Shared/BiomeConfig.lua ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/BiomeConfig.lua
2
+
3
+ local BiomeConfig = {
4
+ Biomes = {
5
+ Forest = {
6
+ TerrainMaterial = Enum.Material.Grass,
7
+ GroundColor = Color3.fromRGB(85, 120, 60),
8
+ TreeTypes = {"Oak", "Birch", "Elm"},
9
+ TreeDensity = 0.08, -- trees per stud^2 (in spawn region)
10
+ ElevationRange = {0, 5},
11
+ HazardType = nil,
12
+ FogEnd = 1500,
13
+ FogColor = Color3.fromRGB(180, 200, 180),
14
+ Region = {MinX = -500, MaxX = -1, MinZ = 1, MaxZ = 500},
15
+ },
16
+ PineWoods = {
17
+ TerrainMaterial = Enum.Material.Grass,
18
+ GroundColor = Color3.fromRGB(60, 95, 45),
19
+ TreeTypes = {"Pine", "Birch"},
20
+ TreeDensity = 0.10,
21
+ ElevationRange = {5, 20},
22
+ HazardType = nil,
23
+ FogEnd = 1200,
24
+ FogColor = Color3.fromRGB(160, 180, 160),
25
+ Region = {MinX = 1, MaxX = 500, MinZ = 1, MaxZ = 500},
26
+ },
27
+ Swamp = {
28
+ TerrainMaterial = Enum.Material.Mud,
29
+ GroundColor = Color3.fromRGB(70, 80, 50),
30
+ TreeTypes = {"Oak", "Elm"},
31
+ TreeDensity = 0.04,
32
+ ElevationRange = {-3, 0},
33
+ HazardType = "SwampZone",
34
+ FogEnd = 600,
35
+ FogColor = Color3.fromRGB(120, 140, 100),
36
+ Region = {MinX = -500, MaxX = -1, MinZ = -500, MaxZ = -1},
37
+ },
38
+ Desert = {
39
+ TerrainMaterial = Enum.Material.Sand,
40
+ GroundColor = Color3.fromRGB(210, 190, 140),
41
+ TreeTypes = {"Elm"},
42
+ TreeDensity = 0.01,
43
+ ElevationRange = {0, 10},
44
+ HazardType = nil,
45
+ FogEnd = 2000,
46
+ FogColor = Color3.fromRGB(230, 220, 180),
47
+ Region = {MinX = 501, MaxX = 1000, MinZ = -500, MaxZ = -1},
48
+ },
49
+ Volcanic = {
50
+ TerrainMaterial = Enum.Material.Basalt,
51
+ GroundColor = Color3.fromRGB(60, 40, 35),
52
+ TreeTypes = {"LavaWood"},
53
+ TreeDensity = 0.02,
54
+ ElevationRange = {10, 40},
55
+ HazardType = "HazardZone",
56
+ HazardAttribute = "Lava",
57
+ FogEnd = 800,
58
+ FogColor = Color3.fromRGB(180, 100, 60),
59
+ Region = {MinX = 501, MaxX = 1000, MinZ = 1, MaxZ = 500},
60
+ },
61
+ IcePeak = {
62
+ TerrainMaterial = Enum.Material.Glacier,
63
+ GroundColor = Color3.fromRGB(200, 220, 240),
64
+ TreeTypes = {"Pine", "Birch"},
65
+ TreeDensity = 0.03,
66
+ ElevationRange = {20, 60},
67
+ HazardType = nil,
68
+ FogEnd = 900,
69
+ FogColor = Color3.fromRGB(210, 220, 240),
70
+ Region = {MinX = -1000, MaxX = -501, MinZ = -500, MaxZ = -1},
71
+ },
72
+ TropicalRainforest = {
73
+ TerrainMaterial = Enum.Material.LeafyGrass,
74
+ GroundColor = Color3.fromRGB(40, 100, 35),
75
+ TreeTypes = {"Mahogany", "Walnut", "GlowWood"},
76
+ TreeDensity = 0.12,
77
+ ElevationRange = {0, 8},
78
+ HazardType = nil,
79
+ FogEnd = 500,
80
+ FogColor = Color3.fromRGB(100, 150, 100),
81
+ Region = {MinX = -1000, MaxX = -501, MinZ = 1, MaxZ = 500},
82
+ },
83
+ Meadow = {
84
+ TerrainMaterial = Enum.Material.Grass,
85
+ GroundColor = Color3.fromRGB(130, 170, 80),
86
+ TreeTypes = {"Oak", "Birch"},
87
+ TreeDensity = 0.02,
88
+ ElevationRange = {0, 3},
89
+ HazardType = nil,
90
+ FogEnd = 2000,
91
+ FogColor = Color3.fromRGB(200, 210, 200),
92
+ Region = {MinX = 1, MaxX = 500, MinZ = -500, MaxZ = -1},
93
+ },
94
+ },
95
+
96
+ -- Terrain generation
97
+ TerrainChunkSize = 64, -- studs per terrain block
98
+ TerrainResolution = 4, -- voxel resolution
99
+ WaterLevel = -2,
100
+
101
+ -- Tree spacing
102
+ MinTreeSpacing = 12, -- minimum studs between trees
103
+ }
104
+
105
+ return BiomeConfig
src/ReplicatedStorage/Shared/BuildingConfig.lua ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/BuildingConfig.lua
2
+
3
+ local BuildingConfig = {
4
+ GridSnap = 2,
5
+ MaxPlacementDistance = 30,
6
+
7
+ Structures = {
8
+ WoodWall = {
9
+ Name = "Wooden Wall",
10
+ Size = Vector3.new(10, 10, 1),
11
+ Cost = {
12
+ WoodVolume = 20,
13
+ SpecificMaterial = "Plank",
14
+ },
15
+ },
16
+ WoodFloor = {
17
+ Name = "Wooden Floor",
18
+ Size = Vector3.new(10, 1, 10),
19
+ Cost = {
20
+ WoodVolume = 25,
21
+ SpecificMaterial = "Plank",
22
+ },
23
+ },
24
+ WoodRoof = {
25
+ Name = "Wooden Roof",
26
+ Size = Vector3.new(12, 1, 12),
27
+ Cost = {
28
+ WoodVolume = 15,
29
+ SpecificMaterial = "Plank",
30
+ },
31
+ },
32
+ WoodDoor = {
33
+ Name = "Wooden Door",
34
+ Size = Vector3.new(4, 8, 1),
35
+ Cost = {
36
+ WoodVolume = 10,
37
+ SpecificMaterial = "Plank",
38
+ },
39
+ },
40
+ WoodStairs = {
41
+ Name = "Wooden Stairs",
42
+ Size = Vector3.new(4, 10, 10),
43
+ Cost = {
44
+ WoodVolume = 30,
45
+ SpecificMaterial = "Plank",
46
+ },
47
+ },
48
+ WoodWindow = {
49
+ Name = "Wooden Window Frame",
50
+ Size = Vector3.new(6, 6, 1),
51
+ Cost = {
52
+ WoodVolume = 12,
53
+ SpecificMaterial = "Plank",
54
+ },
55
+ },
56
+ WoodFence = {
57
+ Name = "Wooden Fence",
58
+ Size = Vector3.new(10, 4, 1),
59
+ Cost = {
60
+ WoodVolume = 8,
61
+ SpecificMaterial = "Stripped",
62
+ },
63
+ },
64
+ WoodBridge = {
65
+ Name = "Wooden Bridge",
66
+ Size = Vector3.new(6, 1, 16),
67
+ Cost = {
68
+ WoodVolume = 40,
69
+ SpecificMaterial = "Plank",
70
+ },
71
+ },
72
+ StonePillar = {
73
+ Name = "Stone Pillar",
74
+ Size = Vector3.new(3, 12, 3),
75
+ Cost = {
76
+ WoodVolume = 5, -- Mortar binding
77
+ SpecificMaterial = "Raw",
78
+ },
79
+ },
80
+ WoodShelter = {
81
+ Name = "Rain Shelter",
82
+ Size = Vector3.new(14, 8, 14),
83
+ Cost = {
84
+ WoodVolume = 50,
85
+ SpecificMaterial = "Plank",
86
+ },
87
+ },
88
+ },
89
+
90
+ -- Structure type cycle order for BuildController
91
+ StructureOrder = {
92
+ "WoodWall", "WoodFloor", "WoodRoof", "WoodDoor",
93
+ "WoodStairs", "WoodWindow", "WoodFence", "WoodBridge",
94
+ "StonePillar", "WoodShelter",
95
+ },
96
+ }
97
+
98
+ return BuildingConfig
src/ReplicatedStorage/Shared/ChoppingConfig.lua ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/ChoppingConfig.lua
2
+ local ChoppingConfig = {
3
+ -- Tree configuration
4
+ TreeTypes = {
5
+ Oak = {
6
+ HealthPerSegment = 100,
7
+ LogColor = Color3.fromRGB(133, 94, 66),
8
+ Density = 0.7,
9
+ ValueMult = 1.0,
10
+ },
11
+ Pine = {
12
+ HealthPerSegment = 80,
13
+ LogColor = Color3.fromRGB(158, 127, 98),
14
+ Density = 0.5,
15
+ ValueMult = 0.8,
16
+ },
17
+ Birch = {
18
+ HealthPerSegment = 60,
19
+ LogColor = Color3.fromRGB(220, 215, 200),
20
+ Density = 0.4,
21
+ ValueMult = 1.2,
22
+ },
23
+ Walnut = {
24
+ HealthPerSegment = 120,
25
+ LogColor = Color3.fromRGB(80, 50, 30),
26
+ Density = 0.8,
27
+ ValueMult = 1.8,
28
+ },
29
+ Mahogany = {
30
+ HealthPerSegment = 150,
31
+ LogColor = Color3.fromRGB(100, 40, 20),
32
+ Density = 0.9,
33
+ ValueMult = 2.5,
34
+ },
35
+ Elm = {
36
+ HealthPerSegment = 90,
37
+ LogColor = Color3.fromRGB(110, 80, 55),
38
+ Density = 0.6,
39
+ ValueMult = 1.0,
40
+ },
41
+ Redwood = {
42
+ HealthPerSegment = 200,
43
+ LogColor = Color3.fromRGB(120, 50, 30),
44
+ Density = 1.0,
45
+ ValueMult = 3.0,
46
+ },
47
+ GlowWood = {
48
+ HealthPerSegment = 70,
49
+ LogColor = Color3.fromRGB(60, 180, 80),
50
+ Density = 0.3,
51
+ ValueMult = 4.0,
52
+ },
53
+ LavaWood = {
54
+ HealthPerSegment = 130,
55
+ LogColor = Color3.fromRGB(50, 30, 20),
56
+ Density = 1.2,
57
+ ValueMult = 5.0,
58
+ },
59
+ -- Mutation types
60
+ Fireproof = {
61
+ HealthPerSegment = 180,
62
+ LogColor = Color3.fromRGB(255, 100, 0),
63
+ Density = 1.1,
64
+ ValueMult = 6.0,
65
+ },
66
+ Glowing = {
67
+ HealthPerSegment = 90,
68
+ LogColor = Color3.fromRGB(0, 255, 100),
69
+ Density = 0.5,
70
+ ValueMult = 7.0,
71
+ },
72
+ Frozen = {
73
+ HealthPerSegment = 50,
74
+ LogColor = Color3.fromRGB(150, 200, 255),
75
+ Density = 0.9,
76
+ ValueMult = 4.5,
77
+ },
78
+ Crystalline = {
79
+ HealthPerSegment = 250,
80
+ LogColor = Color3.fromRGB(200, 160, 255),
81
+ Density = 1.5,
82
+ ValueMult = 10.0,
83
+ },
84
+ },
85
+
86
+ -- Axe configuration
87
+ AxeTypes = {
88
+ BasicAxe = {
89
+ Damage = 25,
90
+ SwingCooldown = 0.8,
91
+ Range = 6,
92
+ },
93
+ SteelAxe = {
94
+ Damage = 50,
95
+ SwingCooldown = 0.6,
96
+ Range = 7,
97
+ },
98
+ GoldAxe = {
99
+ Damage = 80,
100
+ SwingCooldown = 0.5,
101
+ Range = 8,
102
+ },
103
+ DiamondAxe = {
104
+ Damage = 120,
105
+ SwingCooldown = 0.4,
106
+ Range = 9,
107
+ },
108
+ },
109
+
110
+ -- General Physics logic limits
111
+ MinSegmentSizeY = 1.5,
112
+ MaxSegmentSizeY = 8,
113
+ }
114
+
115
+ return ChoppingConfig
src/ReplicatedStorage/Shared/Constants.lua ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/Constants.lua
2
+
3
+ local Constants = {}
4
+
5
+ -- CollectionService Tags
6
+ Constants.Tags = {
7
+ TreeSegment = "TreeSegment",
8
+ TreeModel = "TreeModel",
9
+ Draggable = "Draggable",
10
+ Blueprint = "Blueprint",
11
+ ConstructedPart = "ConstructedPart",
12
+ EmptyPlot = "EmptyPlot",
13
+ ClaimedPlot = "ClaimedPlot",
14
+ MarketDropoff = "MarketDropoff",
15
+ ShopCounter = "ShopCounter",
16
+ BoxedItem = "BoxedItem",
17
+ ProcessingMachine = "ProcessingMachine",
18
+ Vehicle = "Vehicle",
19
+ DronePad = "DronePad",
20
+ HazardZone = "HazardZone",
21
+ SwampZone = "SwampZone",
22
+ WeightSwitch = "WeightSwitch",
23
+ LogicSource = "LogicSource",
24
+ SwampTires = "SwampTires",
25
+ NPC = "NPC",
26
+ BiomeZone = "BiomeZone",
27
+ WorldBoundary = "WorldBoundary",
28
+ SpawnPlatform = "SpawnPlatform",
29
+ }
30
+
31
+ -- Attributes
32
+ Constants.Attributes = {
33
+ TreeType = "TreeType",
34
+ Health = "Health",
35
+ ProcessState = "ProcessState",
36
+ OwnerId = "OwnerId",
37
+ ItemId = "ItemId",
38
+ FillLevel = "FillLevel",
39
+ WoodFilled = "WoodFilled",
40
+ WoodRequired = "WoodRequired",
41
+ StructureType = "StructureType",
42
+ MaterialRequired = "MaterialRequired",
43
+ MachineType = "MachineType",
44
+ DegradedMult = "DegradedMult",
45
+ Mutated = "Mutated",
46
+ HazardType = "HazardType",
47
+ ComponentType = "ComponentType",
48
+ SourceType = "SourceType",
49
+ TargetFunction = "TargetFunction",
50
+ ConveyorSpeed = "ConveyorSpeed",
51
+ Purchased = "Purchased",
52
+ EquippedAxe = "EquippedAxe",
53
+ BiomeName = "BiomeName",
54
+ }
55
+
56
+ -- Process States
57
+ Constants.ProcessStates = {
58
+ Raw = "Raw",
59
+ Stripped = "Stripped",
60
+ Plank = "Plank",
61
+ }
62
+
63
+ return Constants
src/ReplicatedStorage/Shared/CraftingConfig.lua ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/CraftingConfig.lua
2
+
3
+ local CraftingConfig = {
4
+ -- Punch (fist) stats
5
+ Fist = {
6
+ Damage = 5,
7
+ SwingCooldown = 1.2,
8
+ Range = 5,
9
+ },
10
+
11
+ -- Resources dropped per chop hit
12
+ WoodDropChance = 0.6, -- 60% chance to drop resource per hit
13
+ WoodDropAmount = {1, 3}, -- random amount per drop
14
+
15
+ -- Crafting recipes
16
+ Recipes = {
17
+ BasicAxe = {
18
+ Name = "Basic Axe",
19
+ Materials = {
20
+ Wood = 10,
21
+ },
22
+ CraftTime = 2,
23
+ },
24
+ SteelAxe = {
25
+ Name = "Steel Axe",
26
+ Materials = {
27
+ Wood = 30,
28
+ Stone = 5,
29
+ },
30
+ CraftTime = 4,
31
+ },
32
+ GoldAxe = {
33
+ Name = "Gold Axe",
34
+ Materials = {
35
+ Wood = 50,
36
+ Stone = 15,
37
+ GoldOre = 10,
38
+ },
39
+ CraftTime = 6,
40
+ },
41
+ DiamondAxe = {
42
+ Name = "Diamond Axe",
43
+ Materials = {
44
+ Wood = 80,
45
+ Stone = 30,
46
+ GoldOre = 20,
47
+ Diamond = 5,
48
+ },
49
+ CraftTime = 10,
50
+ },
51
+ },
52
+
53
+ -- Resource types and how they are gathered
54
+ Resources = {
55
+ Wood = {
56
+ Source = "TreeSegment",
57
+ Color = Color3.fromRGB(160, 120, 80),
58
+ },
59
+ Stone = {
60
+ Source = "Rock",
61
+ Color = Color3.fromRGB(140, 140, 140),
62
+ },
63
+ GoldOre = {
64
+ Source = "GoldVein",
65
+ Color = Color3.fromRGB(255, 200, 50),
66
+ },
67
+ Diamond = {
68
+ Source = "DiamondVein",
69
+ Color = Color3.fromRGB(100, 200, 255),
70
+ },
71
+ },
72
+ }
73
+
74
+ return CraftingConfig
src/ReplicatedStorage/Shared/DraggingConfig.lua ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/DraggingConfig.lua
2
+ local DraggingConfig = {
3
+ MaxGrabDistance = 15, -- How far away the player can grab an object
4
+ HoldDistance = 6, -- The distance at which the object is held in front of the player
5
+
6
+ -- AlignPosition Properties
7
+ AlignPositionMaxForce = 20000,
8
+ AlignPositionResponsiveness = 15,
9
+
10
+ -- AlignOrientation Properties
11
+ AlignOrientationMaxTorque = 20000,
12
+ AlignOrientationResponsiveness = 20,
13
+ }
14
+
15
+ return DraggingConfig
src/ReplicatedStorage/Shared/EconomyConfig.lua ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/EconomyConfig.lua
2
+
3
+ local EconomyConfig = {
4
+ -- Base values per unit (Stud^3 roughly) of raw wood
5
+ WoodBaseValues = {
6
+ Oak = 15,
7
+ Pine = 10,
8
+ Birch = 18,
9
+ Walnut = 25,
10
+ Mahogany = 35,
11
+ Elm = 12,
12
+ Redwood = 45,
13
+ GlowWood = 60,
14
+ LavaWood = 80,
15
+ Fireproof = 100,
16
+ Glowing = 120,
17
+ Frozen = 70,
18
+ Crystalline = 200,
19
+ },
20
+
21
+ -- Processing multipliers
22
+ ProcessingMultipliers = {
23
+ Raw = 1.0,
24
+ Stripped = 1.5,
25
+ Plank = 2.5,
26
+ },
27
+
28
+ -- Market fluctuation settings
29
+ MarketFluctuations = {
30
+ Enabled = true,
31
+ UpdateInterval = 300,
32
+ MaxIncrease = 1.3,
33
+ MaxDecrease = 0.7,
34
+ },
35
+
36
+ -- Starter cash amount
37
+ StarterCash = 500,
38
+ }
39
+
40
+ return EconomyConfig
src/ReplicatedStorage/Shared/ExplorationConfig.lua ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/ExplorationConfig.lua
2
+
3
+ local ExplorationConfig = {
4
+ Puzzles = {
5
+ WeightSwitch = {
6
+ RequiredWeight = 500,
7
+ ActiveTime = 0,
8
+ },
9
+ LightReceptor = {
10
+ RequiredIntensity = 0.8,
11
+ },
12
+ },
13
+
14
+ Biomes = {
15
+ Swamp = {
16
+ SinkingSpeed = 2,
17
+ DamagePerSecond = 5,
18
+ },
19
+ IcePeak = {
20
+ SlipFriction = 0.05,
21
+ FreezeDamage = 2,
22
+ },
23
+ Desert = {
24
+ HeatDamagePerSecond = 1,
25
+ StaminaDrainMult = 1.5,
26
+ },
27
+ Volcanic = {
28
+ LavaDamagePerSecond = 20,
29
+ SafeDistance = 10,
30
+ },
31
+ TropicalRainforest = {
32
+ VisibilityRange = 100,
33
+ PoisonChance = 0.1,
34
+ },
35
+ Tundra = {
36
+ FreezeDamage = 3,
37
+ SlowMult = 0.7,
38
+ },
39
+ },
40
+ }
41
+
42
+ return ExplorationConfig
src/ReplicatedStorage/Shared/GameConfig.lua ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/GameConfig.lua
2
+
3
+ local GameConfig = {
4
+ -- Starting values
5
+ StarterCash = 500,
6
+ StarterAxe = "BasicAxe",
7
+
8
+ -- Leaderstats
9
+ Stats = {
10
+ Cash = "Cash",
11
+ WoodChopped = "WoodChopped",
12
+ },
13
+
14
+ -- World boundaries
15
+ WorldBounds = {
16
+ MinX = -1500,
17
+ MaxX = 1500,
18
+ MinZ = -1500,
19
+ MaxZ = 1500,
20
+ },
21
+
22
+ -- Spawn area
23
+ SpawnPosition = Vector3.new(0, 5, 0),
24
+ SpawnPlatformSize = Vector3.new(60, 1, 60),
25
+
26
+ -- Auto-save
27
+ AutoSaveInterval = 120, -- seconds
28
+
29
+ -- Max players per server
30
+ MaxPlayers = 12,
31
+
32
+ -- Plot spawn positions (evenly spaced)
33
+ PlotPositions = {
34
+ Vector3.new(120, 0.5, 0),
35
+ Vector3.new(240, 0.5, 0),
36
+ Vector3.new(120, 0.5, 220),
37
+ Vector3.new(240, 0.5, 220),
38
+ Vector3.new(-120, 0.5, 0),
39
+ Vector3.new(-240, 0.5, 0),
40
+ Vector3.new(-120, 0.5, 220),
41
+ Vector3.new(-240, 0.5, 220),
42
+ Vector3.new(120, 0.5, -220),
43
+ Vector3.new(240, 0.5, -220),
44
+ Vector3.new(-120, 0.5, -220),
45
+ Vector3.new(-240, 0.5, -220),
46
+ },
47
+
48
+ -- Market area
49
+ MarketPosition = Vector3.new(0, 0.5, -100),
50
+ MarketSize = Vector3.new(40, 10, 40),
51
+
52
+ -- Shop area
53
+ ShopPosition = Vector3.new(60, 0.5, -100),
54
+ ShopSize = Vector3.new(30, 12, 30),
55
+ }
56
+
57
+ return GameConfig
src/ReplicatedStorage/Shared/MutationConfig.lua ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/MutationConfig.lua
2
+
3
+ local MutationConfig = {
4
+ Hazards = {
5
+ Lava = {
6
+ Radius = 50,
7
+ MutationChance = 0.5,
8
+ ModifiedType = "Fireproof",
9
+ ValueMult = 2.5,
10
+ Material = Enum.Material.Neon,
11
+ Color = Color3.fromRGB(255, 100, 0),
12
+ },
13
+ Toxic = {
14
+ Radius = 60,
15
+ MutationChance = 0.3,
16
+ ModifiedType = "Glowing",
17
+ ValueMult = 3.0,
18
+ Material = Enum.Material.Neon,
19
+ Color = Color3.fromRGB(0, 255, 100),
20
+ },
21
+ Frozen = {
22
+ Radius = 45,
23
+ MutationChance = 0.4,
24
+ ModifiedType = "Frozen",
25
+ ValueMult = 2.0,
26
+ Material = Enum.Material.Ice,
27
+ Color = Color3.fromRGB(150, 200, 255),
28
+ },
29
+ Crystalline = {
30
+ Radius = 30,
31
+ MutationChance = 0.15,
32
+ ModifiedType = "Crystalline",
33
+ ValueMult = 5.0,
34
+ Material = Enum.Material.Glass,
35
+ Color = Color3.fromRGB(200, 160, 255),
36
+ },
37
+ },
38
+ }
39
+
40
+ return MutationConfig
src/ReplicatedStorage/Shared/NPCConfig.lua ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/NPCConfig.lua
2
+
3
+ local NPCConfig = {
4
+ NPCs = {
5
+ Lumberjack_Larry = {
6
+ DisplayName = "Larry the Lumberjack",
7
+ Position = Vector3.new(10, 3, -80),
8
+ BodyColors = {
9
+ HeadColor = Color3.fromRGB(234, 184, 146),
10
+ TorsoColor = Color3.fromRGB(180, 40, 40),
11
+ LeftArmColor = Color3.fromRGB(234, 184, 146),
12
+ RightArmColor = Color3.fromRGB(234, 184, 146),
13
+ LeftLegColor = Color3.fromRGB(50, 50, 130),
14
+ RightLegColor = Color3.fromRGB(50, 50, 130),
15
+ },
16
+ Dialogue = {
17
+ "Welcome to Timberbound Expeditions, partner!",
18
+ "Grab your axe and start choppin' trees!",
19
+ "Process logs at the sawmill for better prices.",
20
+ "Watch out for the rain -- it ruins unprotected wood!",
21
+ },
22
+ QuestIds = {"ChopFirstTree", "Chop10Trees"},
23
+ Role = "Guide",
24
+ },
25
+ Shopkeeper_Sue = {
26
+ DisplayName = "Sue's Supply Shop",
27
+ Position = Vector3.new(60, 3, -90),
28
+ BodyColors = {
29
+ HeadColor = Color3.fromRGB(234, 184, 146),
30
+ TorsoColor = Color3.fromRGB(50, 150, 50),
31
+ LeftArmColor = Color3.fromRGB(234, 184, 146),
32
+ RightArmColor = Color3.fromRGB(234, 184, 146),
33
+ LeftLegColor = Color3.fromRGB(90, 70, 50),
34
+ RightLegColor = Color3.fromRGB(90, 70, 50),
35
+ },
36
+ Dialogue = {
37
+ "Welcome to my shop! Take a look around.",
38
+ "I've got axes, sawmills, and more!",
39
+ "Drag items to the counter and talk to me to buy.",
40
+ },
41
+ QuestIds = {"BuyFirstItem"},
42
+ Role = "Shopkeeper",
43
+ },
44
+ Market_Mike = {
45
+ DisplayName = "Market Mike",
46
+ Position = Vector3.new(0, 3, -110),
47
+ BodyColors = {
48
+ HeadColor = Color3.fromRGB(180, 140, 100),
49
+ TorsoColor = Color3.fromRGB(200, 180, 50),
50
+ LeftArmColor = Color3.fromRGB(180, 140, 100),
51
+ RightArmColor = Color3.fromRGB(180, 140, 100),
52
+ LeftLegColor = Color3.fromRGB(40, 40, 40),
53
+ RightLegColor = Color3.fromRGB(40, 40, 40),
54
+ },
55
+ Dialogue = {
56
+ "Bring your wood here and I'll buy it!",
57
+ "Planks are worth more than raw logs.",
58
+ "Market prices shift every few minutes. Sell smart!",
59
+ },
60
+ QuestIds = {"SellFirstWood", "Earn5000"},
61
+ Role = "Buyer",
62
+ },
63
+ Explorer_Eva = {
64
+ DisplayName = "Explorer Eva",
65
+ Position = Vector3.new(-30, 3, -80),
66
+ BodyColors = {
67
+ HeadColor = Color3.fromRGB(210, 170, 130),
68
+ TorsoColor = Color3.fromRGB(100, 70, 40),
69
+ LeftArmColor = Color3.fromRGB(210, 170, 130),
70
+ RightArmColor = Color3.fromRGB(210, 170, 130),
71
+ LeftLegColor = Color3.fromRGB(60, 80, 50),
72
+ RightLegColor = Color3.fromRGB(60, 80, 50),
73
+ },
74
+ Dialogue = {
75
+ "This world is full of secrets!",
76
+ "Different biomes have different tree types.",
77
+ "Some rare woods glow in the dark... and they're worth a fortune!",
78
+ "Have you found the volcanic region yet?",
79
+ },
80
+ QuestIds = {"ExploreAllBiomes"},
81
+ Role = "Explorer",
82
+ },
83
+ },
84
+ }
85
+
86
+ return NPCConfig
src/ReplicatedStorage/Shared/PlotConfig.lua ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/PlotConfig.lua
2
+ local PlotConfig = {
3
+ GridSize = 2, -- Grid snapping increment in studs
4
+ MaxItemsPerPlot = 1000, -- Limit for performance
5
+
6
+ -- Dimensions of the claimable land
7
+ PlotDimensions = Vector3.new(200, 1, 200),
8
+ }
9
+
10
+ return PlotConfig
src/ReplicatedStorage/Shared/QuestConfig.lua ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/QuestConfig.lua
2
+
3
+ local QuestConfig = {
4
+ Quests = {
5
+ ChopFirstTree = {
6
+ Title = "First Timber",
7
+ Description = "Chop down your first tree segment.",
8
+ Type = "Chop",
9
+ Target = 1,
10
+ Reward = {Cash = 100},
11
+ Icon = "rbxassetid://0", -- placeholder
12
+ },
13
+ Chop10Trees = {
14
+ Title = "Getting Started",
15
+ Description = "Chop 10 tree segments.",
16
+ Type = "Chop",
17
+ Target = 10,
18
+ Reward = {Cash = 500},
19
+ Icon = "rbxassetid://0",
20
+ },
21
+ Chop50Trees = {
22
+ Title = "Lumberjack",
23
+ Description = "Chop 50 tree segments.",
24
+ Type = "Chop",
25
+ Target = 50,
26
+ Reward = {Cash = 2500},
27
+ Icon = "rbxassetid://0",
28
+ },
29
+ Chop200Trees = {
30
+ Title = "Master Forester",
31
+ Description = "Chop 200 tree segments.",
32
+ Type = "Chop",
33
+ Target = 200,
34
+ Reward = {Cash = 10000},
35
+ Icon = "rbxassetid://0",
36
+ },
37
+ SellFirstWood = {
38
+ Title = "First Sale",
39
+ Description = "Sell wood at the market for the first time.",
40
+ Type = "Sell",
41
+ Target = 1,
42
+ Reward = {Cash = 200},
43
+ Icon = "rbxassetid://0",
44
+ },
45
+ Earn5000 = {
46
+ Title = "Money Maker",
47
+ Description = "Earn a total of $5,000 from selling wood.",
48
+ Type = "EarnCash",
49
+ Target = 5000,
50
+ Reward = {Cash = 1000},
51
+ Icon = "rbxassetid://0",
52
+ },
53
+ Earn50000 = {
54
+ Title = "Timber Tycoon",
55
+ Description = "Earn a total of $50,000.",
56
+ Type = "EarnCash",
57
+ Target = 50000,
58
+ Reward = {Cash = 10000},
59
+ Icon = "rbxassetid://0",
60
+ },
61
+ BuildFirstStructure = {
62
+ Title = "Builder",
63
+ Description = "Construct your first building.",
64
+ Type = "Build",
65
+ Target = 1,
66
+ Reward = {Cash = 300},
67
+ Icon = "rbxassetid://0",
68
+ },
69
+ Build10Structures = {
70
+ Title = "Architect",
71
+ Description = "Construct 10 buildings.",
72
+ Type = "Build",
73
+ Target = 10,
74
+ Reward = {Cash = 3000},
75
+ Icon = "rbxassetid://0",
76
+ },
77
+ ExploreAllBiomes = {
78
+ Title = "Explorer",
79
+ Description = "Visit every biome in the world.",
80
+ Type = "Explore",
81
+ Target = 8, -- number of biomes
82
+ Reward = {Cash = 5000},
83
+ Icon = "rbxassetid://0",
84
+ },
85
+ ProcessFirstPlank = {
86
+ Title = "Mill Worker",
87
+ Description = "Process a log into a plank at the sawmill.",
88
+ Type = "Process",
89
+ Target = 1,
90
+ Reward = {Cash = 150},
91
+ Icon = "rbxassetid://0",
92
+ },
93
+ BuyFirstItem = {
94
+ Title = "First Purchase",
95
+ Description = "Buy an item from the shop.",
96
+ Type = "Purchase",
97
+ Target = 1,
98
+ Reward = {Cash = 100},
99
+ Icon = "rbxassetid://0",
100
+ },
101
+ },
102
+
103
+ -- Quest ordering (which quests unlock first)
104
+ StarterQuests = {"ChopFirstTree", "SellFirstWood", "BuildFirstStructure", "BuyFirstItem"},
105
+ }
106
+
107
+ return QuestConfig
src/ReplicatedStorage/Shared/ShopConfig.lua ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/ShopConfig.lua
2
+
3
+ local ShopConfig = {
4
+ Items = {
5
+ BasicAxe = {
6
+ Price = 0, -- Free starter tool
7
+ Name = "Basic Axe",
8
+ Type = "Tool",
9
+ Description = "A simple axe for chopping trees.",
10
+ },
11
+ SteelAxe = {
12
+ Price = 1200,
13
+ Name = "Steel Axe",
14
+ Type = "Tool",
15
+ Description = "Stronger than basic. Faster swings.",
16
+ },
17
+ GoldAxe = {
18
+ Price = 5000,
19
+ Name = "Gold Axe",
20
+ Type = "Tool",
21
+ Description = "High damage with quick recovery.",
22
+ },
23
+ DiamondAxe = {
24
+ Price = 25000,
25
+ Name = "Diamond Axe",
26
+ Type = "Tool",
27
+ Description = "The ultimate axe. Cuts anything fast.",
28
+ },
29
+ BarkStripper = {
30
+ Price = 800,
31
+ Name = "Bark Stripper Machine",
32
+ Type = "Machine",
33
+ Description = "Strips bark from raw logs.",
34
+ },
35
+ Sawmill = {
36
+ Price = 3500,
37
+ Name = "Basic Sawmill",
38
+ Type = "Machine",
39
+ Description = "Converts logs into valuable planks.",
40
+ },
41
+ AdvancedSawmill = {
42
+ Price = 15000,
43
+ Name = "Advanced Sawmill",
44
+ Type = "Machine",
45
+ Description = "Processes logs faster and cleaner.",
46
+ },
47
+ Conveyor = {
48
+ Price = 500,
49
+ Name = "Conveyor Belt",
50
+ Type = "Machine",
51
+ Description = "Moves items automatically.",
52
+ },
53
+ Flatbed = {
54
+ Price = 8000,
55
+ Name = "Flatbed Truck",
56
+ Type = "Vehicle",
57
+ Description = "Transport large loads of lumber.",
58
+ },
59
+ BasicDrone = {
60
+ Price = 12000,
61
+ Name = "Basic Delivery Drone",
62
+ Type = "Automation",
63
+ Description = "Automatically carries small loads.",
64
+ },
65
+ AdvancedDrone = {
66
+ Price = 35000,
67
+ Name = "Advanced Delivery Drone",
68
+ Type = "Automation",
69
+ Description = "Carries heavy loads at high speed.",
70
+ },
71
+ WoodShelter = {
72
+ Price = 2000,
73
+ Name = "Rain Shelter Kit",
74
+ Type = "Structure",
75
+ Description = "Protects wood from rain degradation.",
76
+ },
77
+ WireKit = {
78
+ Price = 300,
79
+ Name = "Wire Kit",
80
+ Type = "Utility",
81
+ Description = "Connect components with wires.",
82
+ },
83
+ Button = {
84
+ Price = 200,
85
+ Name = "Logic Button",
86
+ Type = "Component",
87
+ Description = "Wire source: sends pulse signal.",
88
+ },
89
+ Lever = {
90
+ Price = 250,
91
+ Name = "Logic Lever",
92
+ Type = "Component",
93
+ Description = "Wire source: toggles on/off.",
94
+ },
95
+ },
96
+
97
+ -- Category ordering for ship GUI
98
+ Categories = {"Tool", "Machine", "Vehicle", "Automation", "Structure", "Utility", "Component"},
99
+
100
+ -- Items per category (for display ordering)
101
+ CategoryItems = {
102
+ Tool = {"BasicAxe", "SteelAxe", "GoldAxe", "DiamondAxe"},
103
+ Machine = {"BarkStripper", "Sawmill", "AdvancedSawmill", "Conveyor"},
104
+ Vehicle = {"Flatbed"},
105
+ Automation = {"BasicDrone", "AdvancedDrone"},
106
+ Structure = {"WoodShelter"},
107
+ Utility = {"WireKit"},
108
+ Component = {"Button", "Lever"},
109
+ },
110
+ }
111
+
112
+ return ShopConfig
src/ReplicatedStorage/Shared/SoundConfig.lua ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/SoundConfig.lua
2
+ -- Sound asset IDs (using Roblox default content where available)
3
+
4
+ local SoundConfig = {
5
+ -- Tool Sounds
6
+ AxeSwing = "rbxasset://sounds/snap.mp3",
7
+ AxeHitWood = "rbxasset://sounds/impact_wood.mp3",
8
+ TreeFall = "rbxasset://sounds/bass.mp3",
9
+
10
+ -- Economy
11
+ CashRegister = "rbxasset://sounds/electronicpingshort.wav",
12
+ PurchaseSuccess = "rbxasset://sounds/electronicpingshort.wav",
13
+ PurchaseFail = "rbxasset://sounds/bass.mp3",
14
+
15
+ -- Building
16
+ PlaceBlueprint = "rbxasset://sounds/snap.mp3",
17
+ ConstructComplete = "rbxasset://sounds/electronicpingshort.wav",
18
+
19
+ -- UI
20
+ ButtonClick = "rbxasset://sounds/snap.mp3",
21
+ QuestComplete = "rbxasset://sounds/electronicpingshort.wav",
22
+ Notification = "rbxasset://sounds/electronicpingshort.wav",
23
+
24
+ -- Weather ambient
25
+ RainLoop = "rbxasset://sounds/bass.mp3",
26
+ WindLoop = "rbxasset://sounds/snap.mp3",
27
+
28
+ -- General ambient
29
+ ForestAmbient = "rbxasset://sounds/snap.mp3",
30
+ SwampAmbient = "rbxasset://sounds/bass.mp3",
31
+
32
+ -- Volume levels
33
+ MasterVolume = 0.8,
34
+ SFXVolume = 1.0,
35
+ MusicVolume = 0.5,
36
+ AmbientVolume = 0.3,
37
+ }
38
+
39
+ return SoundConfig
src/ReplicatedStorage/Shared/TreeModelConfig.lua ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/TreeModelConfig.lua
2
+
3
+ local TreeModelConfig = {
4
+ Templates = {
5
+ Oak = {
6
+ TrunkDiameter = {2.5, 3.5}, -- min, max
7
+ TrunkHeight = {12, 20},
8
+ SegmentCount = {3, 5},
9
+ CanopyRadius = {6, 10},
10
+ CanopySegments = 5,
11
+ LeafColor = Color3.fromRGB(50, 120, 40),
12
+ LeafMaterial = Enum.Material.LeafyGrass,
13
+ BarkColor = Color3.fromRGB(133, 94, 66),
14
+ BarkMaterial = Enum.Material.Wood,
15
+ HasLeaves = true,
16
+ },
17
+ Pine = {
18
+ TrunkDiameter = {1.5, 2.5},
19
+ TrunkHeight = {15, 25},
20
+ SegmentCount = {4, 6},
21
+ CanopyRadius = {3, 5},
22
+ CanopySegments = 6,
23
+ LeafColor = Color3.fromRGB(30, 80, 30),
24
+ LeafMaterial = Enum.Material.LeafyGrass,
25
+ BarkColor = Color3.fromRGB(158, 127, 98),
26
+ BarkMaterial = Enum.Material.Wood,
27
+ HasLeaves = true,
28
+ ConicalCanopy = true,
29
+ },
30
+ Birch = {
31
+ TrunkDiameter = {1.5, 2.0},
32
+ TrunkHeight = {14, 22},
33
+ SegmentCount = {4, 6},
34
+ CanopyRadius = {4, 7},
35
+ CanopySegments = 4,
36
+ LeafColor = Color3.fromRGB(100, 170, 60),
37
+ LeafMaterial = Enum.Material.LeafyGrass,
38
+ BarkColor = Color3.fromRGB(220, 215, 200),
39
+ BarkMaterial = Enum.Material.Marble,
40
+ HasLeaves = true,
41
+ },
42
+ Walnut = {
43
+ TrunkDiameter = {2.0, 3.0},
44
+ TrunkHeight = {10, 16},
45
+ SegmentCount = {3, 4},
46
+ CanopyRadius = {5, 8},
47
+ CanopySegments = 5,
48
+ LeafColor = Color3.fromRGB(60, 100, 30),
49
+ LeafMaterial = Enum.Material.LeafyGrass,
50
+ BarkColor = Color3.fromRGB(80, 50, 30),
51
+ BarkMaterial = Enum.Material.Wood,
52
+ HasLeaves = true,
53
+ },
54
+ Mahogany = {
55
+ TrunkDiameter = {3.0, 4.5},
56
+ TrunkHeight = {18, 28},
57
+ SegmentCount = {5, 7},
58
+ CanopyRadius = {8, 12},
59
+ CanopySegments = 6,
60
+ LeafColor = Color3.fromRGB(40, 90, 25),
61
+ LeafMaterial = Enum.Material.LeafyGrass,
62
+ BarkColor = Color3.fromRGB(100, 40, 20),
63
+ BarkMaterial = Enum.Material.Wood,
64
+ HasLeaves = true,
65
+ },
66
+ Elm = {
67
+ TrunkDiameter = {2.0, 3.0},
68
+ TrunkHeight = {12, 18},
69
+ SegmentCount = {3, 5},
70
+ CanopyRadius = {5, 9},
71
+ CanopySegments = 5,
72
+ LeafColor = Color3.fromRGB(80, 140, 50),
73
+ LeafMaterial = Enum.Material.LeafyGrass,
74
+ BarkColor = Color3.fromRGB(110, 80, 55),
75
+ BarkMaterial = Enum.Material.Wood,
76
+ HasLeaves = true,
77
+ },
78
+ Redwood = {
79
+ TrunkDiameter = {4.0, 6.0},
80
+ TrunkHeight = {30, 50},
81
+ SegmentCount = {6, 10},
82
+ CanopyRadius = {6, 10},
83
+ CanopySegments = 4,
84
+ LeafColor = Color3.fromRGB(35, 70, 30),
85
+ LeafMaterial = Enum.Material.LeafyGrass,
86
+ BarkColor = Color3.fromRGB(120, 50, 30),
87
+ BarkMaterial = Enum.Material.Wood,
88
+ HasLeaves = true,
89
+ },
90
+ GlowWood = {
91
+ TrunkDiameter = {1.5, 2.5},
92
+ TrunkHeight = {8, 14},
93
+ SegmentCount = {3, 4},
94
+ CanopyRadius = {4, 6},
95
+ CanopySegments = 4,
96
+ LeafColor = Color3.fromRGB(0, 255, 100),
97
+ LeafMaterial = Enum.Material.Neon,
98
+ BarkColor = Color3.fromRGB(60, 180, 80),
99
+ BarkMaterial = Enum.Material.SmoothPlastic,
100
+ HasLeaves = true,
101
+ GlowTrunk = true,
102
+ },
103
+ LavaWood = {
104
+ TrunkDiameter = {2.0, 3.5},
105
+ TrunkHeight = {8, 14},
106
+ SegmentCount = {3, 4},
107
+ CanopyRadius = {3, 5},
108
+ CanopySegments = 3,
109
+ LeafColor = Color3.fromRGB(255, 120, 0),
110
+ LeafMaterial = Enum.Material.Neon,
111
+ BarkColor = Color3.fromRGB(50, 30, 20),
112
+ BarkMaterial = Enum.Material.CrackedLava,
113
+ HasLeaves = true,
114
+ GlowTrunk = true,
115
+ },
116
+ },
117
+ }
118
+
119
+ return TreeModelConfig
src/ReplicatedStorage/Shared/Utility.lua ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/Utility.lua
2
+
3
+ local Utility = {}
4
+
5
+ function Utility.formatCash(amount)
6
+ if amount >= 1000000 then
7
+ return string.format("$%.1fM", amount / 1000000)
8
+ elseif amount >= 1000 then
9
+ return string.format("$%.1fK", amount / 1000)
10
+ else
11
+ return "$" .. tostring(math.floor(amount))
12
+ end
13
+ end
14
+
15
+ function Utility.formatTime(seconds)
16
+ local min = math.floor(seconds / 60)
17
+ local sec = math.floor(seconds % 60)
18
+ return string.format("%d:%02d", min, sec)
19
+ end
20
+
21
+ function Utility.lerp(a, b, t)
22
+ return a + (b - a) * t
23
+ end
24
+
25
+ function Utility.getPartVolume(part)
26
+ if not part or not part:IsA("BasePart") then return 0 end
27
+ return part.Size.X * part.Size.Y * part.Size.Z
28
+ end
29
+
30
+ function Utility.randomInRange(min, max)
31
+ return min + math.random() * (max - min)
32
+ end
33
+
34
+ function Utility.randomIntInRange(min, max)
35
+ return math.random(min, max)
36
+ end
37
+
38
+ function Utility.clampVector3(vec, minBounds, maxBounds)
39
+ return Vector3.new(
40
+ math.clamp(vec.X, minBounds.X, maxBounds.X),
41
+ math.clamp(vec.Y, minBounds.Y, maxBounds.Y),
42
+ math.clamp(vec.Z, minBounds.Z, maxBounds.Z)
43
+ )
44
+ end
45
+
46
+ function Utility.shuffleTable(tbl)
47
+ local shuffled = {}
48
+ for _, v in ipairs(tbl) do
49
+ table.insert(shuffled, v)
50
+ end
51
+ for i = #shuffled, 2, -1 do
52
+ local j = math.random(1, i)
53
+ shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
54
+ end
55
+ return shuffled
56
+ end
57
+
58
+ function Utility.tableContains(tbl, value)
59
+ for _, v in ipairs(tbl) do
60
+ if v == value then return true end
61
+ end
62
+ return false
63
+ end
64
+
65
+ function Utility.tableKeys(tbl)
66
+ local keys = {}
67
+ for k, _ in pairs(tbl) do
68
+ table.insert(keys, k)
69
+ end
70
+ return keys
71
+ end
72
+
73
+ function Utility.deepCopy(original)
74
+ local copy = {}
75
+ for k, v in pairs(original) do
76
+ if type(v) == "table" then
77
+ copy[k] = Utility.deepCopy(v)
78
+ else
79
+ copy[k] = v
80
+ end
81
+ end
82
+ return copy
83
+ end
84
+
85
+ return Utility
src/ReplicatedStorage/Shared/VehicleConfig.lua ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/VehicleConfig.lua
2
+ local VehicleConfig = {
3
+ -- Physical properties for the truck bed to prevent logs from sliding off easily while driving
4
+ -- Density, Friction, Elasticity, FrictionWeight, ElasticityWeight
5
+ -- Extremely high Friction and FrictionWeight to lock the logs to the bed
6
+ FlatbedPhysicalProperties = PhysicalProperties.new(1.0, 2.0, 0, 100, 100),
7
+
8
+ CollisionGroups = {
9
+ Logs = "Logs",
10
+ Vehicles = "Vehicles",
11
+ }
12
+ }
13
+
14
+ return VehicleConfig
src/ReplicatedStorage/Shared/WeatherConfig.lua ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/WeatherConfig.lua
2
+
3
+ local WeatherConfig = {
4
+ CycleDurationMin = 300, -- 5 mins of clear weather
5
+ CycleDurationMax = 600, -- 10 mins
6
+
7
+ RainDurationMin = 60, -- 1 minute of rain
8
+ RainDurationMax = 180, -- 3 minutes of rain
9
+
10
+ DegradationConfig = {
11
+ WoodValueLossPerTick = 0.05, -- 5% loss per tick
12
+ TickInterval = 3, -- Every 3 seconds in rain
13
+ MaxValueLoss = 0.5, -- Logs won't lose more than 50% of value
14
+ }
15
+ }
16
+
17
+ return WeatherConfig
src/ReplicatedStorage/Shared/WireLogicConfig.lua ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ReplicatedStorage/Shared/WireLogicConfig.lua
2
+
3
+ local WireLogicConfig = {
4
+ MaxWireLength = 50, -- Maximum distance between two connected nodes
5
+
6
+ -- Defining the kinds of components available
7
+ ComponentTypes = {
8
+ Source = {"Button", "Lever", "PressurePlate"},
9
+ Logic = {"AND", "OR", "NOT", "Delay", "Timer"},
10
+ Target = {"Door", "Sawmill", "Conveyor", "Light"}
11
+ }
12
+ }
13
+
14
+ return WireLogicConfig
src/ServerScriptService/AchievementManager.server.lua ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ServerScriptService/AchievementManager.server.lua
2
+
3
+ local Players = game:GetService("Players")
4
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
5
+
6
+ local NotificationEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("NotificationEvent")
7
+
8
+ -- Achievement definitions
9
+ local Achievements = {
10
+ {id = "first_chop", title = "First Swing", description = "Chop your first tree segment", stat = "WoodChopped", target = 1},
11
+ {id = "chop_100", title = "Century Cutter", description = "Chop 100 tree segments", stat = "WoodChopped", target = 100},
12
+ {id = "chop_500", title = "Lumber Legend", description = "Chop 500 tree segments", stat = "WoodChopped", target = 500},
13
+ {id = "chop_1000", title = "Timber Titan", description = "Chop 1000 tree segments", stat = "WoodChopped", target = 1000},
14
+ {id = "earn_1000", title = "First Thousand", description = "Earn $1,000 total", stat = "TotalEarned", target = 1000},
15
+ {id = "earn_10000", title = "Money Bags", description = "Earn $10,000 total", stat = "TotalEarned", target = 10000},
16
+ {id = "earn_100000", title = "Timber Mogul", description = "Earn $100,000 total", stat = "TotalEarned", target = 100000},
17
+ {id = "build_1", title = "First Foundation", description = "Build your first structure", stat = "TotalBuilt", target = 1},
18
+ {id = "build_25", title = "Master Builder", description = "Build 25 structures", stat = "TotalBuilt", target = 25},
19
+ }
20
+
21
+ -- Track awarded achievements per player
22
+ local playerAchievements = {} -- [userId] = {achievementId = true, ...}
23
+
24
+ local function checkAchievements(player)
25
+ local data = _G.GetPlayerData(player)
26
+ if not data then return end
27
+
28
+ if not playerAchievements[player.UserId] then
29
+ playerAchievements[player.UserId] = {}
30
+ end
31
+
32
+ local leaderstats = player:FindFirstChild("leaderstats")
33
+
34
+ for _, achievement in ipairs(Achievements) do
35
+ if playerAchievements[player.UserId][achievement.id] then continue end
36
+
37
+ local currentValue = 0
38
+
39
+ -- Check leaderstats
40
+ if leaderstats then
41
+ local stat = leaderstats:FindFirstChild(achievement.stat)
42
+ if stat then
43
+ currentValue = stat.Value
44
+ end
45
+ end
46
+
47
+ -- Check player data
48
+ if data[achievement.stat] then
49
+ currentValue = data[achievement.stat]
50
+ end
51
+
52
+ if currentValue >= achievement.target then
53
+ playerAchievements[player.UserId][achievement.id] = true
54
+ NotificationEvent:FireClient(player, "Achievement", achievement.title .. " - " .. achievement.description)
55
+ end
56
+ end
57
+ end
58
+
59
+ -- Expose for other managers
60
+ _G.CheckAchievements = function(player)
61
+ checkAchievements(player)
62
+ end
63
+
64
+ _G.GetPlayerAchievements = function(player)
65
+ return playerAchievements[player.UserId] or {}
66
+ end
67
+
68
+ -- Periodic check
69
+ task.spawn(function()
70
+ while true do
71
+ task.wait(10)
72
+ for _, player in ipairs(Players:GetPlayers()) do
73
+ pcall(function()
74
+ checkAchievements(player)
75
+ end)
76
+ end
77
+ end
78
+ end)
79
+
80
+ Players.PlayerRemoving:Connect(function(player)
81
+ playerAchievements[player.UserId] = nil
82
+ end)
src/ServerScriptService/AntiCheatManager.server.lua ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ServerScriptService/AntiCheatManager.server.lua
2
+
3
+ local Players = game:GetService("Players")
4
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
5
+
6
+ -- Rate limiting tracker
7
+ local rateLimits = {} -- [userId] = { [eventName] = { count, lastReset } }
8
+
9
+ local MAX_EVENTS_PER_SECOND = 10
10
+ local RATE_WINDOW = 1 -- seconds
11
+
12
+ local function getRateData(player, eventName)
13
+ if not rateLimits[player.UserId] then
14
+ rateLimits[player.UserId] = {}
15
+ end
16
+ if not rateLimits[player.UserId][eventName] then
17
+ rateLimits[player.UserId][eventName] = {
18
+ count = 0,
19
+ lastReset = tick(),
20
+ }
21
+ end
22
+ return rateLimits[player.UserId][eventName]
23
+ end
24
+
25
+ -- Check if a player is rate limited
26
+ _G.IsRateLimited = function(player, eventName)
27
+ local data = getRateData(player, eventName)
28
+ local now = tick()
29
+
30
+ if now - data.lastReset > RATE_WINDOW then
31
+ data.count = 0
32
+ data.lastReset = now
33
+ end
34
+
35
+ data.count = data.count + 1
36
+
37
+ if data.count > MAX_EVENTS_PER_SECOND then
38
+ warn("Rate limit exceeded for " .. player.Name .. " on event " .. eventName)
39
+ return true
40
+ end
41
+
42
+ return false
43
+ end
44
+
45
+ -- Validate distance between player and target
46
+ _G.ValidateDistance = function(player, targetPosition, maxDistance)
47
+ local character = player.Character
48
+ if not character then return false end
49
+
50
+ local rootPart = character:FindFirstChild("HumanoidRootPart")
51
+ if not rootPart then return false end
52
+
53
+ local distance = (rootPart.Position - targetPosition).Magnitude
54
+ return distance <= maxDistance
55
+ end
56
+
57
+ -- Validate player has enough cash
58
+ _G.ValidateCash = function(player, amount)
59
+ local leaderstats = player:FindFirstChild("leaderstats")
60
+ if not leaderstats then return false end
61
+
62
+ local cash = leaderstats:FindFirstChild("Cash")
63
+ if not cash then return false end
64
+
65
+ return cash.Value >= amount
66
+ end
67
+
68
+ -- Cleanup on player leave
69
+ Players.PlayerRemoving:Connect(function(player)
70
+ rateLimits[player.UserId] = nil
71
+ end)
72
+
73
+ print("Anti-Cheat Manager initialized")
src/ServerScriptService/BiomeGeneratorManager.server.lua ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ServerScriptService/BiomeGeneratorManager.server.lua
2
+ -- Simple flat baseplate-style world with colored biome regions
3
+
4
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
5
+ local CollectionService = game:GetService("CollectionService")
6
+
7
+ local BiomeConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("BiomeConfig"))
8
+ local GameConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("GameConfig"))
9
+
10
+ -- Create folders
11
+ local biomeZonesFolder = Instance.new("Folder")
12
+ biomeZonesFolder.Name = "BiomeZones"
13
+ biomeZonesFolder.Parent = workspace
14
+
15
+ local worldFolder = Instance.new("Folder")
16
+ worldFolder.Name = "WorldStructures"
17
+ worldFolder.Parent = workspace
18
+
19
+ -- Biome color map (distinct flat colors, no grass)
20
+ local BiomeColors = {
21
+ Forest = Color3.fromRGB(80, 130, 60),
22
+ PineWoods = Color3.fromRGB(50, 100, 45),
23
+ Swamp = Color3.fromRGB(65, 85, 50),
24
+ Desert = Color3.fromRGB(210, 190, 130),
25
+ Volcanic = Color3.fromRGB(70, 40, 35),
26
+ IcePeak = Color3.fromRGB(190, 210, 230),
27
+ TropicalRainforest = Color3.fromRGB(35, 110, 40),
28
+ Meadow = Color3.fromRGB(140, 180, 80),
29
+ }
30
+
31
+ local function createBiomePlate(biomeName, biomeData)
32
+ local region = biomeData.Region
33
+ local regionWidth = region.MaxX - region.MinX
34
+ local regionDepth = region.MaxZ - region.MinZ
35
+ local centerX = (region.MinX + region.MaxX) / 2
36
+ local centerZ = (region.MinZ + region.MaxZ) / 2
37
+
38
+ -- Flat baseplate for this biome
39
+ local plate = Instance.new("Part")
40
+ plate.Name = biomeName .. "_Plate"
41
+ plate.Size = Vector3.new(regionWidth, 1, regionDepth)
42
+ plate.Position = Vector3.new(centerX, -0.5, centerZ) -- Top surface at Y=0
43
+ plate.Anchored = true
44
+ plate.Material = Enum.Material.SmoothPlastic
45
+ plate.Color = BiomeColors[biomeName] or Color3.fromRGB(100, 100, 100)
46
+ plate.TopSurface = Enum.SurfaceType.Smooth
47
+ plate.BottomSurface = Enum.SurfaceType.Smooth
48
+ plate.Parent = biomeZonesFolder
49
+
50
+ -- Invisible detection zone (taller, for biome detection)
51
+ local zonePart = Instance.new("Part")
52
+ zonePart.Name = biomeName .. "_Zone"
53
+ zonePart.Size = Vector3.new(regionWidth, 50, regionDepth)
54
+ zonePart.Position = Vector3.new(centerX, 25, centerZ)
55
+ zonePart.Anchored = true
56
+ zonePart.CanCollide = false
57
+ zonePart.Transparency = 1
58
+ zonePart:SetAttribute("BiomeName", biomeName)
59
+ CollectionService:AddTag(zonePart, "BiomeZone")
60
+ zonePart.Parent = biomeZonesFolder
61
+
62
+ -- Hazard zone if applicable
63
+ if biomeData.HazardType then
64
+ local hazardZone = Instance.new("Part")
65
+ hazardZone.Name = biomeName .. "_Hazard"
66
+ hazardZone.Size = Vector3.new(regionWidth * 0.8, 20, regionDepth * 0.8)
67
+ hazardZone.Position = Vector3.new(centerX, 10, centerZ)
68
+ hazardZone.Anchored = true
69
+ hazardZone.CanCollide = false
70
+ hazardZone.Transparency = 0.95
71
+ hazardZone.BrickColor = BrickColor.new("Bright red")
72
+
73
+ if biomeData.HazardAttribute then
74
+ hazardZone:SetAttribute("HazardType", biomeData.HazardAttribute)
75
+ end
76
+
77
+ CollectionService:AddTag(hazardZone, biomeData.HazardType)
78
+ hazardZone.Parent = biomeZonesFolder
79
+ end
80
+
81
+ -- Biome label sign at center
82
+ local signPart = Instance.new("Part")
83
+ signPart.Name = biomeName .. "_Sign"
84
+ signPart.Size = Vector3.new(8, 4, 0.5)
85
+ signPart.Position = Vector3.new(centerX, 4, centerZ)
86
+ signPart.Anchored = true
87
+ signPart.Material = Enum.Material.Wood
88
+ signPart.BrickColor = BrickColor.new("Reddish brown")
89
+ signPart.Parent = biomeZonesFolder
90
+
91
+ local signGui = Instance.new("SurfaceGui")
92
+ signGui.Face = Enum.NormalId.Front
93
+ signGui.Parent = signPart
94
+
95
+ local signLabel = Instance.new("TextLabel")
96
+ signLabel.Size = UDim2.new(1, 0, 1, 0)
97
+ signLabel.BackgroundTransparency = 1
98
+ signLabel.Text = biomeName
99
+ signLabel.TextColor3 = Color3.new(1, 1, 1)
100
+ signLabel.TextScaled = true
101
+ signLabel.Font = Enum.Font.GothamBold
102
+ signLabel.Parent = signGui
103
+
104
+ print("Biome plate created:", biomeName)
105
+ end
106
+
107
+ -- Create spawn platform (elevated slightly so it is distinct)
108
+ local function createSpawnPlatform()
109
+ local platform = Instance.new("Part")
110
+ platform.Name = "SpawnPlatform"
111
+ platform.Size = Vector3.new(GameConfig.SpawnPlatformSize.X, 0.2, GameConfig.SpawnPlatformSize.Z)
112
+ platform.Position = Vector3.new(GameConfig.SpawnPosition.X, 0.1, GameConfig.SpawnPosition.Z) -- rests slightly above biome plate
113
+ platform.Anchored = true
114
+ platform.Material = Enum.Material.SmoothPlastic
115
+ platform.Color = Color3.fromRGB(160, 160, 165)
116
+ platform.TopSurface = Enum.SurfaceType.Smooth
117
+ platform.BottomSurface = Enum.SurfaceType.Smooth
118
+ CollectionService:AddTag(platform, "SpawnPlatform")
119
+ platform.Parent = worldFolder
120
+
121
+ local spawn = Instance.new("SpawnLocation")
122
+ spawn.Size = Vector3.new(6, 1, 6)
123
+ spawn.Position = Vector3.new(GameConfig.SpawnPosition.X, 0.5, GameConfig.SpawnPosition.Z)
124
+ spawn.Anchored = true
125
+ spawn.CanCollide = false
126
+ spawn.Transparency = 1
127
+ spawn.Parent = worldFolder
128
+ end
129
+
130
+ -- World boundaries
131
+ local function createWorldBoundaries()
132
+ local bounds = GameConfig.WorldBounds
133
+ local height = 200
134
+ local thickness = 5
135
+
136
+ local walls = {
137
+ {pos = Vector3.new(0, height/2, bounds.MinZ), size = Vector3.new(bounds.MaxX - bounds.MinX, height, thickness)},
138
+ {pos = Vector3.new(0, height/2, bounds.MaxZ), size = Vector3.new(bounds.MaxX - bounds.MinX, height, thickness)},
139
+ {pos = Vector3.new(bounds.MinX, height/2, 0), size = Vector3.new(thickness, height, bounds.MaxZ - bounds.MinZ)},
140
+ {pos = Vector3.new(bounds.MaxX, height/2, 0), size = Vector3.new(thickness, height, bounds.MaxZ - bounds.MinZ)},
141
+ }
142
+
143
+ for i, wallData in ipairs(walls) do
144
+ local wall = Instance.new("Part")
145
+ wall.Name = "WorldBoundary_" .. i
146
+ wall.Size = wallData.size
147
+ wall.Position = wallData.pos
148
+ wall.Anchored = true
149
+ wall.Transparency = 1
150
+ wall.CanCollide = true
151
+ CollectionService:AddTag(wall, "WorldBoundary")
152
+ wall.Parent = worldFolder
153
+ end
154
+ end
155
+
156
+ -- Plot areas
157
+ local function createPlots()
158
+ local plotsFolder = Instance.new("Folder")
159
+ plotsFolder.Name = "Plots"
160
+ plotsFolder.Parent = worldFolder
161
+
162
+ for i, pos in ipairs(GameConfig.PlotPositions) do
163
+ local plot = Instance.new("Part")
164
+ plot.Name = "Plot_" .. i
165
+ plot.Size = Vector3.new(200, 0.2, 200)
166
+ plot.Position = Vector3.new(pos.X, 0.1, pos.Z) -- elevate slightly to prevent z-fighting
167
+ plot.Anchored = true
168
+ plot.Material = Enum.Material.SmoothPlastic
169
+ plot.Color = Color3.fromRGB(90, 90, 95)
170
+ plot.TopSurface = Enum.SurfaceType.Smooth
171
+ plot.BottomSurface = Enum.SurfaceType.Smooth
172
+ plot.Transparency = 1 -- fully invisible as requested
173
+ CollectionService:AddTag(plot, "EmptyPlot")
174
+ plot.Parent = plotsFolder
175
+
176
+
177
+ end
178
+ end
179
+
180
+ -- Execute world generation
181
+ task.spawn(function()
182
+ print("=== Timberbound Expeditions: World Generation Starting ===")
183
+
184
+ createSpawnPlatform()
185
+ createWorldBoundaries()
186
+ createPlots()
187
+
188
+ -- Create flat biome plates (no terrain, no elevation)
189
+ for biomeName, biomeData in pairs(BiomeConfig.Biomes) do
190
+ createBiomePlate(biomeName, biomeData)
191
+ end
192
+
193
+ print("=== World Generation Complete ===")
194
+ _G.BiomeGenerationComplete = true
195
+ end)
src/ServerScriptService/ConstructionManager.server.lua ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- src/ServerScriptService/ConstructionManager.server.lua
2
+
3
+ local CollectionService = game:GetService("CollectionService")
4
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
5
+ local Players = game:GetService("Players")
6
+
7
+ local BuildingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("BuildingConfig"))
8
+ local PlaceBlueprintEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("PlaceBlueprintEvent")
9
+ local FillBlueprintEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("FillBlueprintEvent")
10
+
11
+ local function getPartVolume(part)
12
+ return part.Size.X * part.Size.Y * part.Size.Z
13
+ end
14
+
15
+ -- Validate and place a blueprint
16
+ local function onPlaceBlueprint(player, structureType, cframe)
17
+ local config = BuildingConfig.Structures[structureType]
18
+ if not config then return end
19
+
20
+ -- In a real game, you would verify if `cframe` is inside the player's Claimed Plot
21
+ -- Verification skipped here for brevity
22
+
23
+ local blueprintModel = Instance.new("Part")
24
+ blueprintModel.Size = Vector3.new(10, 10, 1) -- Example dimensions
25
+ blueprintModel.CFrame = cframe
26
+
27
+ -- Visual Blueprint state
28
+ blueprintModel.Transparency = 0.5
29
+ blueprintModel.BrickColor = BrickColor.new("Neon blue")
30
+ blueprintModel.Material = Enum.Material.ForceField
31
+ blueprintModel.Anchored = true
32
+
33
+ -- Attributes for tracking
34
+ blueprintModel:SetAttribute("StructureType", structureType)
35
+ blueprintModel:SetAttribute("WoodFilled", 0)
36
+ blueprintModel:SetAttribute("WoodRequired", config.Cost.WoodVolume)
37
+ blueprintModel:SetAttribute("MaterialRequired", config.Cost.SpecificMaterial)
38
+ blueprintModel:SetAttribute("OwnerId", player.UserId)
39
+
40
+ CollectionService:AddTag(blueprintModel, "Blueprint")
41
+
42
+ blueprintModel.Parent = workspace.Terrain
43
+
44
+ -- Bind touched event so players can "throw" wood into the blueprint to fill it
45
+ local debounce = {}
46
+ blueprintModel.Touched:Connect(function(hit)
47
+ -- Make sure it's fully processed wood touching it
48
+ if CollectionService:HasTag(hit, "TreeSegment") and not debounce[hit] then
49
+ debounce[hit] = true
50
+
51
+ local requiredMaterial = blueprintModel:GetAttribute("MaterialRequired")
52
+ local hitMaterial = hit:GetAttribute("ProcessState") or "Raw"
53
+
54
+ if hitMaterial == requiredMaterial then
55
+ local volume = getPartVolume(hit)
56
+
57
+ local currentFill = blueprintModel:GetAttribute("WoodFilled")
58
+ local required = blueprintModel:GetAttribute("WoodRequired")
59
+
60
+ local newFill = currentFill + volume
61
+ blueprintModel:SetAttribute("WoodFilled", newFill)
62
+
63
+ -- Visual feedback: change transparency based on fill %
64
+ local fillPercent = math.clamp(newFill / required, 0, 1)
65
+ blueprintModel.Transparency = 0.5 - (0.5 * fillPercent)
66
+
67
+ hit:Destroy()
68
+
69
+ if newFill >= required then
70
+ -- Construct!
71
+ blueprintModel.Transparency = 0
72
+ blueprintModel.BrickColor = BrickColor.new("Burlap")
73
+ blueprintModel.Material = Enum.Material.WoodPlanks
74
+ blueprintModel.CanCollide = true
75
+
76
+ CollectionService:RemoveTag(blueprintModel, "Blueprint")
77
+ CollectionService:AddTag(blueprintModel, "ConstructedPart")
78
+ end
79
+ end
80
+
81
+ task.delay(0.5, function()
82
+ debounce[hit] = nil
83
+ end)
84
+ end
85
+ end)
86
+ end
87
+
88
+ PlaceBlueprintEvent.OnServerEvent:Connect(onPlaceBlueprint)