Compare commits

..

16 Commits

Author SHA1 Message Date
Lucien Greathouse
c856a3e361 Release 0.4.7 2018-05-25 23:31:01 -07:00
Lucien Greathouse
aa5f0cc335 Issue a warning if no partitions are specified during serve.
Closes #40
2018-05-22 11:04:53 -07:00
Lucien Greathouse
b067335bbf Update CHANGES 2018-05-22 10:55:23 -07:00
Jonathan Holmes
7d24a14004 Added plugin icons to Rojo (#70) 2018-05-22 10:52:55 -07:00
Lucien Greathouse
910be640e9 Release 0.4.6 2018-05-21 13:26:25 -07:00
Lucien Greathouse
3137753afa Update CHANGES 2018-05-21 13:09:00 -07:00
Lucien Greathouse
000ff351a5 Improve plugin handling with regards to restarts and UI
Closes #67.
2018-05-21 13:05:52 -07:00
Lucien Greathouse
533c8ddaf7 Update CHANGES 2018-05-21 12:55:41 -07:00
Lucien Greathouse
f777d1b6c6 Update CHANGES 2018-05-21 12:52:46 -07:00
Lucien Greathouse
8b17d3b7d9 Intense robustness pass 2018-05-21 12:48:25 -07:00
Lucien Greathouse
6fbe1daf8e Add folder for testing script duplication bug 2018-05-21 12:47:51 -07:00
Lucien Greathouse
3bd191414b Update CHANGES 2018-05-21 11:45:55 -07:00
Lucien Greathouse
fd2cb3495b Make reconciler more robust with regards to RouteMap 2018-05-21 11:21:31 -07:00
Lucien Greathouse
e9d33bdc02 Skip reparenting if parent is the same 2018-05-21 11:16:56 -07:00
Lucien Greathouse
c0f4b31ab3 Make sure all descendants get removed from the RouteMap 2018-05-21 10:40:06 -07:00
Lucien Greathouse
78de30dcf2 Fix missing colon in plugin stopped polling message 2018-05-01 14:36:25 -07:00
14 changed files with 134 additions and 50 deletions

View File

@@ -1,7 +1,19 @@
# Rojo Change Log
## Current Master
*No changes*
## Current master
* *No changes*
## 0.4.7 (May 25, 2018)
* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70))
* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/LPGhatguy/rojo/issues/40))
## 0.4.6 (May 21, 2018)
* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67))
* Folders should no longer get collapsed when syncing occurs.
* **Significant** robustness improvements with regards to caching.
* **This should catch all existing script duplication bugs.**
* If there are any bugs with script duplication or caching in the future, restarting the Rojo server process will fix them for that session.
* Fixed message in plugin not being prefixed with `Rojo: `.
## 0.4.5 (May 1, 2018)
* Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more.

View File

@@ -8,7 +8,7 @@
<a href="https://travis-ci.org/LPGhatguy/rojo">
<img src="https://api.travis-ci.org/LPGhatguy/rojo.svg?branch=master" alt="Travis-CI Build Status" />
</a>
<img src="https://img.shields.io/badge/latest_version-0.4.5-brightgreen.svg" alt="Current server version" />
<img src="https://img.shields.io/badge/latest_version-0.4.7-brightgreen.svg" alt="Current server version" />
<a href="https://lpghatguy.github.io/rojo">
<img src="https://img.shields.io/badge/documentation-website-brightgreen.svg" alt="Rojo Documentation" />
</a>

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

BIN
assets/rojo-sync-in.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

BIN
assets/rojo-test-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

View File

@@ -1,7 +1,12 @@
return {
pollingRate = 0.2,
version = {0, 4, 5},
version = {0, 4, 7},
expectedServerVersionString = "0.4.x",
protocolVersion = 1,
icons = {
syncIn = "rbxassetid://1820320573",
togglePolling = "rbxassetid://1820320064",
testConnection = "rbxassetid://1820320989",
},
dev = false,
}

View File

@@ -45,7 +45,7 @@ local function main()
local toolbar = plugin:CreateToolbar("Rojo Plugin " .. displayedVersion)
toolbar:CreateButton("Test Connection", "Connect to Rojo Server", "")
toolbar:CreateButton("Test Connection", "Connect to Rojo Server", Config.icons.testConnection)
.Click:Connect(function()
checkUpgrade()
@@ -55,7 +55,7 @@ local function main()
end)
end)
toolbar:CreateButton("Sync In", "Sync into Roblox Studio", "")
toolbar:CreateButton("Sync In", "Sync into Roblox Studio", Config.icons.syncIn)
.Click:Connect(function()
checkUpgrade()
@@ -65,7 +65,7 @@ local function main()
end)
end)
toolbar:CreateButton("Toggle Polling", "Poll server for changes", "")
toolbar:CreateButton("Toggle Polling", "Poll server for changes", Config.icons.togglePolling)
.Click:Connect(function()
checkUpgrade()

View File

@@ -1,9 +1,12 @@
local CoreGui = game:GetService("CoreGui")
local Promise = require(script.Parent.Parent.modules.Promise)
local Config = require(script.Parent.Config)
local Http = require(script.Parent.Http)
local Api = require(script.Parent.Api)
local Reconciler = require(script.Parent.Reconciler)
local Version = require(script.Parent.Version)
local function collectMatch(source, pattern)
local result = {}
@@ -35,9 +38,23 @@ function Plugin.new()
setmetatable(self, Plugin)
do
local uiName = ("Rojo %s UI"):format(Version.display(Config.version))
if Config.dev then
uiName = "Rojo Dev UI"
end
-- If there's an existing Rojo UI, like from a Roblox plugin upgrade
-- that wasn't Rojo, make sure we clean it up.
local existingUi = CoreGui:FindFirstChild(uiName)
if existingUi ~= nil then
existingUi:Destroy()
end
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "Rojo UI"
screenGui.Parent = game.CoreGui
screenGui.Name = uiName
screenGui.Parent = CoreGui
screenGui.DisplayOrder = -1
screenGui.Enabled = false
@@ -54,6 +71,18 @@ function Plugin.new()
label.Parent = screenGui
self._label = screenGui
-- If our UI was destroyed, we assume it was from another instance of
-- the Rojo plugin coming online.
--
-- Roblox doesn't notify plugins when they get unloaded, so this is the
-- best trigger we have right now unless we create a dedicated event
-- object.
screenGui.AncestryChanged:Connect(function(_, parent)
if parent == nil then
self:restart()
end
end)
end
return self
@@ -66,7 +95,11 @@ end
function Plugin:restart()
warn("Rojo: The server has changed since the last request, reloading plugin...")
self._reconciler:clear()
self:stopPolling()
self._reconciler:destruct()
self._reconciler = Reconciler.new()
self._api = nil
self._polling = false
self._syncInProgress = false
@@ -122,7 +155,7 @@ function Plugin:stopPolling()
return Promise.resolve(false)
end
print("Rojo Stopped polling server for changes.")
print("Rojo: Stopped polling server for changes.")
self._polling = false
self._label.Enabled = false

View File

@@ -1,15 +1,32 @@
local RouteMap = require(script.Parent.RouteMap)
local function classEqual(rbx, className)
if className == "*" then
local function classEqual(a, b)
if a == "*" or b == "*" then
return true
end
return rbx.ClassName == className
return a == b
end
local function applyProperties(target, properties)
for key, property in pairs(properties) do
-- TODO: Transform property value based on property.Type
-- Right now, we assume that 'value' is primitive!
target[key] = property.Value
end
end
--[[
Attempt to parent `rbx` to `parent`, doing nothing if:
* parent is already `parent`
* Changing parent threw an error
]]
local function reparent(rbx, parent)
if rbx then
if rbx.Parent == parent then
return
end
-- It's possible that 'rbx' is a service or some other object that we
-- can't change the parent of. That's the only reason why Parent would
-- fail except for rbx being previously destroyed!
@@ -38,7 +55,7 @@ local function findNextChildPair(primaryChildren, secondaryChildren, visited)
visited[primaryChild] = true
for _, secondaryChild in ipairs(secondaryChildren) do
if primaryChild.ClassName == secondaryChild.ClassName and primaryChild.Name == secondaryChild.Name then
if classEqual(primaryChild.ClassName, secondaryChild.ClassName) and primaryChild.Name == secondaryChild.Name then
visited[secondaryChild] = true
return primaryChild, secondaryChild
@@ -110,12 +127,11 @@ function Reconciler:_reify(item)
local rbx = Instance.new(className)
rbx.Name = item.Name
for key, property in pairs(item.Properties) do
-- TODO: Check for compound types, like Vector3!
rbx[key] = property.Value
end
applyProperties(rbx, item.Properties)
self:_reconcileChildren(rbx, item)
for _, child in ipairs(item.Children) do
reparent(self:_reify(child), rbx)
end
if item.Route then
self._routeMap:insert(item.Route, rbx)
@@ -125,10 +141,10 @@ function Reconciler:_reify(item)
end
--[[
Clears any state that the Reconciler has, effectively restarting it.
Clears any state that the Reconciler has, stopping it completely.
]]
function Reconciler:clear()
self._routeMap:clear()
function Reconciler:destruct()
self._routeMap:destruct()
end
--[[
@@ -139,6 +155,7 @@ function Reconciler:reconcile(rbx, item)
-- Item was deleted
if not item then
if rbx then
self._routeMap:removeByRbx(rbx)
rbx:Destroy()
end
@@ -151,27 +168,16 @@ function Reconciler:reconcile(rbx, item)
end
-- Item changed type!
if not classEqual(rbx, item.ClassName) then
if not classEqual(rbx.ClassName, item.ClassName) then
self._routeMap:removeByRbx(rbx)
rbx:Destroy()
rbx = self:_reify(item)
return self:_reify(item)
end
-- Apply all properties, Roblox will de-duplicate changes
for key, property in pairs(item.Properties) do
-- TODO: Transform property value based on property.Type
-- Right now, we assume that 'value' is primitive!
rbx[key] = property.Value
end
-- Use a dumb algorithm for reconciling children
applyProperties(rbx, item.Properties)
self:_reconcileChildren(rbx, item)
if item.Route then
self._routeMap:insert(item.Route, rbx)
end
return rbx
end

View File

@@ -25,6 +25,10 @@ end
function RouteMap:insert(route, rbx)
local hashed = hashRoute(route)
-- Make sure that each route and instance are only present in RouteMap once.
self:removeByRoute(route)
self:removeByRbx(rbx)
self._map[hashed] = rbx
self._reverseMap[rbx] = hashed
self._connectionsByRbx[rbx] = rbx.AncestryChanged:Connect(function(_, parent)
@@ -42,24 +46,36 @@ function RouteMap:removeByRoute(route)
local hashedRoute = hashRoute(route)
local rbx = self._map[hashedRoute]
if rbx then
self._map[hashedRoute] = nil
self._reverseMap[rbx] = nil
self._connectionsByRbx[rbx] = nil
if rbx ~= nil then
self:_removeInternal(hashedRoute, rbx)
end
end
function RouteMap:removeByRbx(rbx)
local hashedRoute = self._reverseMap[rbx]
if hashedRoute then
self._map[hashedRoute] = nil
self._reverseMap[rbx] = nil
self._connectionsByRbx[rbx] = nil
if hashedRoute ~= nil then
self:_removeInternal(hashedRoute, rbx)
end
end
function RouteMap:removeRbxDescendants(parentRbx)
--[[
Correcly removes the given Roblox Instance/Route pair from the RouteMap.
]]
function RouteMap:_removeInternal(rbx, hashedRoute)
self._map[hashedRoute] = nil
self._reverseMap[rbx] = nil
self._connectionsByRbx[rbx]:Disconnect()
self._connectionsByRbx[rbx] = nil
self:removeRbxDescendants(rbx)
end
--[[
Ensure that there are no descendants of the given Roblox Instance still
present in the map, guaranteeing that it has been cleaned out.
]]
function RouteMap:_removeRbxDescendants(parentRbx)
for rbx in pairs(self._reverseMap) do
if rbx:IsDescendantOf(parentRbx) then
self:removeByRbx(rbx)
@@ -67,7 +83,11 @@ function RouteMap:removeRbxDescendants(parentRbx)
end
end
function RouteMap:clear()
--[[
Remove all items from the map and disconnect all connections, cleaning up
the RouteMap.
]]
function RouteMap:destruct()
self._map = {}
self._reverseMap = {}

2
server/Cargo.lock generated
View File

@@ -636,7 +636,7 @@ dependencies = [
[[package]]
name = "rojo"
version = "0.4.5"
version = "0.4.7"
dependencies = [
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,6 +1,6 @@
[package]
name = "rojo"
version = "0.4.5"
version = "0.4.7"
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
description = "A tool to create robust Roblox projects"
license = "MIT"

View File

@@ -44,6 +44,13 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option<u64>) {
},
};
if project.partitions.len() == 0 {
println!("");
println!("This project has no partitions and will not do anything when served!");
println!("This is usually a mistake -- edit rojo.json!");
println!("");
}
lazy_static! {
static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![
Box::new(ScriptPlugin::new()),

1
test-project/src/a/b.lua Normal file
View File

@@ -0,0 +1 @@
print("HEY!")