From b5cc2434669ee813bfd8dede93a24f6d1bded0cb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Apr 2018 00:09:28 -0700 Subject: [PATCH] Flesh out documentation, normalize markdown indentation --- .editorconfig | 5 ++ README.md | 82 ++++++++++----------- docs/getting-started/creating-a-project.md | 77 +++++++++++++++++++ docs/getting-started/installation.md | 23 ++++++ docs/images/connection-error.png | Bin 0 -> 5928 bytes docs/images/plugin-buttons.png | Bin 0 -> 17614 bytes docs/images/sync-example.png | Bin 0 -> 1931 bytes docs/sync-details.md | 61 +++++++++++++++ docs/why-rojo.md | 21 ++++++ mkdocs.yml | 6 ++ 10 files changed, 234 insertions(+), 41 deletions(-) create mode 100644 docs/getting-started/creating-a-project.md create mode 100644 docs/getting-started/installation.md create mode 100644 docs/images/connection-error.png create mode 100644 docs/images/plugin-buttons.png create mode 100644 docs/images/sync-example.png create mode 100644 docs/sync-details.md create mode 100644 docs/why-rojo.md diff --git a/.editorconfig b/.editorconfig index 263d65f2..702598e1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,4 +7,9 @@ charset = utf-8 [*.json] indent_style = space indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +indent_style = space +indent_size = 4 trim_trailing_whitespace = true \ No newline at end of file diff --git a/README.md b/README.md index de72a54c..79ee70c4 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@
- Rojo + Rojo
 
- - Travis-CI Build Status - - Current server version + + Travis-CI Build Status + + Current server version

@@ -45,9 +45,9 @@ To install the server, either: To install the plugin, either: * Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). - * This gives you less control over what version you install -- you will always have the latest version. + * This gives you less control over what version you install -- you will always have the latest version. * Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder - * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio + * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio ## Server Usage For more help, use `rojo help`. @@ -68,9 +68,9 @@ The default project file is: ```json { - "name": "my-new-project", - "servePort": 8000, - "partitions": {} + "name": "my-new-project", + "servePort": 8000, + "partitions": {} } ``` @@ -97,14 +97,14 @@ For example, if you want to map your `src` directory to an object named `My Cool ```json { - "name": "rojo", - "servePort": 8000, - "partitions": { - "game": { - "path": "src", - "target": "ReplicatedStorage.My Cool Game" + "name": "rojo", + "servePort": 8000, + "partitions": { + "game": { + "path": "src", + "target": "ReplicatedStorage.My Cool Game" + } } - } } ``` @@ -140,13 +140,13 @@ Any directory containing one of these files will instead be a `ModuleScript`, `S For example, this file tree: * my-game - * init.client.lua - * foo.lua + * init.client.lua + * foo.lua Will turn into these instances in Roblox: * `my-game` (`LocalScript` with source from `my-game/init.client.lua`) - * `foo` (`ModuleScript` with source from `my-game/foo.lua`) + * `foo` (`ModuleScript` with source from `my-game/foo.lua`) `*.model.json` files are a way to represent simple Roblox instances on the filesystem until `rbxmx` and `rbxlx` support is implemented in Rojo. @@ -156,28 +156,28 @@ JSON Model files are strict, with every property being required. They look like ```json { - "Name": "hello", - "ClassName": "Model", - "Children": [ - { - "Name": "Some Part", - "ClassName": "Part", - "Children": [], - "Properties": {} - }, - { - "Name": "Some StringValue", - "ClassName": "StringValue", - "Children": [], - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" + "Name": "hello", + "ClassName": "Model", + "Children": [ + { + "Name": "Some Part", + "ClassName": "Part", + "Children": [], + "Properties": {} + }, + { + "Name": "Some StringValue", + "ClassName": "StringValue", + "Children": [], + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + } } - } - } - ], - "Properties": {} + ], + "Properties": {} } ``` diff --git a/docs/getting-started/creating-a-project.md b/docs/getting-started/creating-a-project.md new file mode 100644 index 00000000..49dad7fc --- /dev/null +++ b/docs/getting-started/creating-a-project.md @@ -0,0 +1,77 @@ +# Creating a Project +To use Rojo, you'll need to create a new project file, which tells Rojo what your project is, and how to load it into Roblox Studio. + +## New Project +Create a new folder, then run `rojo init` inside that folder to initialize an empty project. + +```sh +mkdir my-new-project +cd my-new-project + +rojo init +``` + +Rojo will create an empty project file named `rojo.json` in the directory. + +The default configuration doesn't do anything. We need to tell Rojo where our code is on the filesystem, and where we want to put it in the Roblox tree. + +To do that, open up `rojo.json` and add an entry to the `partitions` table: + +```json +{ + "name": "your-project-name-here", + "servePort": 8000, + "partitions": { + "src": { + "path": "src", + "target": "ReplicatedStorage.Project" + } + } +} +``` + +!!! warning + Make sure that the `src` directory exists in your project, or Rojo will throw an error! + +!!! warning + Any objects contained in the `target` of a partition will be destroyed by Rojo if not found on the filesystem! + +A Rojo project has one or more *partitions*. Partitions define how code should be transferred between the filesystem and Roblox by mapping directories and files to Roblox objects. + +Each partition has: + +* A name (the key in the `partitions` object), which is used for debugging +* `path`, the location on the filesystem relative to `rojo.json` +* `target`, the location in Roblox relative to `game` + +## Syncing into Studio + +Once you've added your partition to the project file, you can start the Rojo dev server by running a command in your project's directory: + +```sh +rojo serve +``` + +If your project is in the right place, Rojo will let you know that it was found and start an HTTP server that the plugin can connect to. + +In Roblox Studio, open the plugins tab and find Rojo's buttons. + +![Location of Rojo's plugin buttons in Roblox Studio](/images/plugin-buttons.png) +{: align="center" } + +Press **Test Connection** to verify that the plugin can communicate with the dev server. Watch the Output panel for the results. + +!!! info + If you see an error message, return to the previous steps and make sure that the Rojo dev server is running. + + ![Rojo error in Roblox Studio Output](/images/connection-error.png) + {: align="center" } + +After your connection was successful, press **Sync In** to move code from the filesystem into Studio, or use **Toggle Polling** to have Rojo automatically sync in changes as they happen. + +## Importing an Existing Project +Rojo will eventually support importing an existing Roblox project onto the filesystem for use with Rojo. + +Rojo doesn't currently support converting an existing project or syncing files from Roblox Studio onto the filesystem. In the mean time, you can manually copy your files into the structure that Rojo expects. + +Up-to-date information will be available on [issue #5](https://github.com/LPGhatguy/rojo/issues/5) as this is worked on. \ No newline at end of file diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 00000000..2c3c986d --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,23 @@ +# Installation +Rojo has two components: + +* The server, a binary written in Rust +* The plugin, a Roblox Studio plugin written in Lua + +It's important that the plugin and server are compatible. The plugin will show errors in the Roblox Studio Output window if there is a version mismatch. + +## Installing the Server +To install the server, either: + +* If you have Rust installed, use `cargo install rojo` +* Or, download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases) + +**The Rojo binary must be run from the command line, like Terminal on MacOS or `cmd.exe` on Windows. It's recommended that you put the Rojo binary on your `PATH` to make this easier.** + +## Installing the Plugin +To install the plugin, either: + +* Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). + * This gives you less control over what version you install -- you will always have the latest version. +* Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder + * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio \ No newline at end of file diff --git a/docs/images/connection-error.png b/docs/images/connection-error.png new file mode 100644 index 0000000000000000000000000000000000000000..af3c16faa69226f1e3a2e58a4c6fff74be10cab2 GIT binary patch literal 5928 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 gP^_yV_)_OyGr@cJsnFjNpBA%_(f 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 RSAqZl002ovPDHLkV1nI2o$3Gp literal 0 HcmV?d00001 diff --git a/docs/sync-details.md b/docs/sync-details.md new file mode 100644 index 00000000..40dfb285 --- /dev/null +++ b/docs/sync-details.md @@ -0,0 +1,61 @@ +# Sync Details +This page aims to describe how Rojo turns files on the filesystem into Roblox objects. + +## Folders +Any directory on the filesystem will turn into a `Folder` instance in Roblox, unless that folder matches the name of a service or other existing instance. In those cases, that instance will be preserved. + +## Scripts +Rojo can represent `ModuleScript`, `Script`, and `LocalScript` objects. The default script type is `ModuleScript`, since most scripts in well-structued Roblox projects will be modules. + +| File Name | Instance Type | +| -------------- | -------------- | +| `*.server.lua` | `Script` | +| `*.client.lua` | `LocalScript` | +| `*.lua` | `ModuleScript` | + +If a directory contains a file named `init.server.lua`, `init.client.lua`, or `init.lua`, that folder will be transformed into a `*Script` instance with the conents of the `init` file. This can be used to create scripts inside of scripts. + +For example, this file tree: + +* my-game + * init.client.lua + * foo.lua + +Will turn into these instances in Roblox: + +![Example of Roblox instances](/images/sync-example.png) + +## Models +Rojo supports a JSON model format for representing simple models. It's designed for instance types like `BindableEvent` or `*Value` objects, and is not suitable for larger models. + +!!! info + In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. + +JSON model files are strict, with every property being required. They look like this: + +```json +{ + "Name": "hello", + "ClassName": "Model", + "Children": [ + { + "Name": "Some Part", + "ClassName": "Part", + "Children": [], + "Properties": {} + }, + { + "Name": "Some StringValue", + "ClassName": "StringValue", + "Children": [], + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + } + } + ], + "Properties": {} +} +``` \ No newline at end of file diff --git a/docs/why-rojo.md b/docs/why-rojo.md new file mode 100644 index 00000000..b6872309 --- /dev/null +++ b/docs/why-rojo.md @@ -0,0 +1,21 @@ +# Why Rojo? +There are a number of existing plugins for Roblox that move code from the filesystem into Roblox. + +Besides Rojo, there is: + +* [Studio Bridge](https://github.com/vocksel/studio-bridge) by [Vocksel](https://github.com/vocksel) +* [RbxRefresh](https://github.com/osyrisrblx/RbxRefresh) by [Osyris](https://github.com/osyrisrblx) +* [RbxSync](https://github.com/evaera/RbxSync) by [evaera](https://github.com/evaera) +* [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin) +* [rbxmk](https://github.com/anaminus/rbxmk) by [Anaminus](https://github.com/anaminus) + +So why did I build Rojo? + +Each of these tools solves what is essentially the same problem from a few different angles. The goal of Rojo is to take all of the lessons and ideas learned from these projects and build a tool that can solve the problem for good. + +Additionally: + +* I think that this tool needs to be built in a compiled language without a runtime, for easy distribution and good performance. +* I think that the conventions promoted by other sync plugins (`.module.lua` for modules, as well a single sync point) are sub-optimal. +* I think that I have a good enough understanding of the problem to build something robust. +* I think that Rojo should be able to do more than just sync code. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 10529937..703712bf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,8 +11,14 @@ theme: pages: - Home: index.md + - Why Rojo?: why-rojo.md + - Getting Started: + - Installation: getting-started/installation.md + - Creating a Project: getting-started/creating-a-project.md + - Sync Details: sync-details.md markdown_extensions: + - attr_list - admonition - codehilite: guess_lang: false