rojo-rbx / rojo

Rojo enables Roblox developers to use professional-grade software engineering tools
https://rojo.space
Mozilla Public License 2.0
969 stars 182 forks source link

`rojo init --kind place` should produce a structure that mirrors common services #995

Open kennethloeffler opened 2 days ago

kennethloeffler commented 2 days ago

Right now, rojo init --kind place and rojo init (since "place" is the default) produce a file tree like this:

my-place-project/
├─ src/
│  ├─ client/
│  │  └─ init.client.luau
│  ├─ server/
│  │  └─ init.server.luau
│  ├─ shared/
│  │  └─ Hello.luau
├─ .gitignore
├─ default.project.json
└─ README.md

default.project.json contains the following:

{
  "name": "my-place-project",
  "tree": {
    "$className": "DataModel",

    "ReplicatedStorage": {
      "Shared": {
        "$path": "src/shared"
      }
    },

    "ServerScriptService": {
      "Server": {
        "$path": "src/server"
      }
    },

    "StarterPlayer": {
      "StarterPlayerScripts": {
        "Client": {
          "$path": "src/client"
        }
      }
    },

    "Workspace": {
      "$properties": {
        "FilteringEnabled": true
      },
      "Baseplate": {
        "$className": "Part",
        "$properties": {
          "Anchored": true,
          "Color": [
            0.38823,
            0.37254,
            0.38823
          ],
          "Locked": true,
          "Position": [
            0,
            -10,
            0
          ],
          "Size": [
            512,
            20,
            512
          ]
        }
      }
    },
    "Lighting": {
      "$properties": {
        "Ambient": [
          0,
          0,
          0
        ],
        "Brightness": 2,
        "GlobalShadows": true,
        "Outlines": false,
        "Technology": "Voxel"
      }
    },
    "SoundService": {
      "$properties": {
        "RespectFilteringEnabled": true
      }
    }
  }
}

This setup isn't very approachable to new users, mostly because it's not obvious what server, client, and shared map to in the Roblox data model. To find out what will happen to these directories, a new user either has to read and understand the project format, or else sync or build the project and observe the result.

Additionally, the current place template isn't very representative of Rojo's feature set, making it a poor example. It does not include any Roblox model files, JSON model files, or meta files. It's not clear how many different things the default project should demonstrate, but I think at least Roblox models and JSON models should be included.

Lastly, this will make using the upcoming syncback feature (#937) easier. The current place template doesn't lend itself well to syncback's operation.

So, I think Rojo should alter the "place" template so it more closely matches what Roblox users see in Roblox Studio, perhaps something like:

my-place-project/
├─ game/
│  ├─ Lighting/
│  │  ├─ Atmosphere.model.json
│  │  └─ Sky.model.json
│  ├─ ReplicatedFirst/
│  │  └─ .gitkeep [only when project is git repository] 
│  ├─ ReplicatedStorage/
│  │  └─ ModuleScript.luau
│  ├─ ServerScriptService/
│  │  └─ Script.server.luau
│  ├─ ServerStorage/
│  │  └─ .gitkeep [only when project is git repository] 
│  ├─ StarterGui/
│  │  └─ .gitkeep [only when project is git repository] 
│  ├─ StarterPlayer/
│  │  ├─ StarterCharacterScripts/
│  │  │  └─ .gitkeep [only when project is git repository] 
│  │  ├─ StarterPlayerScripts/
│  │  │  └─ LocalScript.client.luau
│  ├─ Workspace/
│  │  └─ Baseplate.rbxm
├─ .gitignore
├─ default.project.json
└─ README.md

The default.project.json would contain something like:

{
  "name": "my-place-project",
  "tree": {
    "$className": "DataModel",

    "Lighting": {
      "$properties": {
        "Ambient": [
          0.5,
          0.5,
          0.5
        ],
        "Brightness": 2.0,
        "GlobalShadows": true,
        "Technology": "ShadowMap"
      },
      "$path": "game/Lighting"
    },

    "ReplicatedFirst": {
      "$path": "game/ReplicatedFirst"
    },

    "ReplicatedStorage": {
      "$path": "game/ReplicatedStorage"
    },

    "ServerScriptService": {
      "$path": "game/ServerScriptService"
    },

    "ServerStorage": {
      "$path": "game/ServerStorage"
    },

    "StarterGui": {
      "$path": "game/StarterGui"
    },

    "StarterPlayer": {
      "StarterPlayerScripts": {
        "$path": "game/StarterPlayer/StarterPlayerScripts"
      },
      "StarterCharacterScripts": {
        "$path": "game/StarterPlayer/StarterCharacterScripts"
      }
    },

    "Workspace": {
      "$path": "game/Workspace"
    }
  }
}

There are some unanswered questions:

Dekkonot commented 2 days ago

I think this would be a good decision, yeah. I have doubts that anybody is actually using rojo init for anything important, but it's not a bad idea to ask around first just to make sure.

jackTabsCode commented 2 days ago

I don't feel strongly on this issue, but I personally prefer keeping my source code in a cohesive structure that I like, rather than trying to conform to Roblox's datamodel scheme, and in my opinion, others should do the same. I think that rojo init producing different folder names, like it does now, helps convey to new users their new freedom to organize their project however they like.

kennethloeffler commented 2 days ago

For people who already have a lot of experience with Rojo, the ability to stray from Roblox conventions is icing on the cake, but for first-time users, it's confusing. I've observed this many times over as I've onboarded new users onto Rojo in professional work and provided support to the broader community. In general, using patterns and terms that are already familiar makes for better UX than immediately diverging, even if the divergence can be seen as better on other axes.

If people want to go deeper into Rojo and leverage all the capabilities it offers to the fullest extent, then that's great, and we can offer support for that when they're ready - but they need to get through the door first!

UpliftMacaw commented 1 day ago

I see empty directories, are we placing a .gitkeep in there or a different file? Git won't pick those up automatically and it may confuse users new to version control.

Dekkonot commented 1 day ago

rojo init initializes git if it can and a repo doesn't exist... It probably makes sense to add .gitkeep if we succeed at initializing a git repo?