Files
rojo/plugin/src/Plugin.lua
Lucien Greathouse 7838b2e67d Initial commit
2017-11-29 17:25:37 -08:00

257 lines
5.1 KiB
Lua

local Config = require(script.Parent.Config)
local Http = require(script.Parent.Http)
local Server = require(script.Parent.Server)
local Promise = require(script.Parent.Promise)
local function collectMatch(source, pattern)
local result = {}
for match in source:gmatch(pattern) do
table.insert(result, match)
end
return result
end
local function fileToName(filename)
if filename:find("%.server%.lua$") then
return filename:match("^(.-)%.server%.lua$"), "Script"
elseif filename:find("%.client%.lua$") then
return filename:match("^(.-)%.client%.lua$"), "LocalScript"
elseif filename:find("%.lua") then
return filename:match("^(.-)%.lua$"), "ModuleScript"
else
return filename, "StringValue"
end
end
local function nameToInstance(filename, contents)
local name, className = fileToName(filename)
local instance = Instance.new(className)
instance.Name = name
if className:find("Script$") then
instance.Source = contents
else
instance.Value = contents
end
return instance
end
local function make(item, name)
if item.type == "dir" then
local instance = Instance.new("Folder")
instance.Name = name
for childName, child in pairs(item.children) do
make(child, childName).Parent = instance
end
return instance
elseif item.type == "file" then
return nameToInstance(name, item.contents)
else
error("not implemented")
end
end
local function write(parent, route, item)
local location = parent
for index = 1, #route - 1 do
local piece = route[index]
local newLocation = location:FindFirstChild(piece)
if not newLocation then
newLocation = Instance.new("Folder")
newLocation.Name = piece
newLocation.Parent = location
end
location = newLocation
end
local fileName = route[#route]
local name = fileToName(fileName)
local existing = location:FindFirstChild(name)
local new
if item then
new = make(item, fileName)
end
if existing then
existing:Destroy()
end
if new then
new.Parent = location
end
end
local Plugin = {}
Plugin.__index = Plugin
function Plugin.new()
local address = "localhost"
local port = 8081
local remote = ("http://%s:%d"):format(address, port)
local foop = {
_http = Http.new(remote),
_server = nil,
_polling = false,
}
setmetatable(foop, Plugin)
do
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "Rojo UI"
screenGui.Parent = game.CoreGui
screenGui.DisplayOrder = -1
screenGui.Enabled = false
local label = Instance.new("TextLabel")
label.Font = Enum.Font.SourceSans
label.TextSize = 20
label.Text = "Rojo polling..."
label.BackgroundColor3 = Color3.fromRGB(31, 31, 31)
label.BackgroundTransparency = 0.5
label.BorderSizePixel = 0
label.TextColor3 = Color3.new(1, 1, 1)
label.Size = UDim2.new(0, 120, 0, 28)
label.Position = UDim2.new(0, 0, 0, 0)
label.Parent = screenGui
foop._label = screenGui
end
return foop
end
function Plugin:server()
if not self._server then
self._server = Server.connect(self._http)
:catch(function(err)
self._server = nil
return Promise.reject(err)
end)
end
return self._server
end
function Plugin:connect()
print("Testing connection...")
self:server()
:andThen(function(server)
return server:getInfo()
end)
:andThen(function(result)
print("Server found!")
print("Protocol version:", result.protocolVersion)
print("Server version:", result.serverVersion)
end)
end
function Plugin:togglePolling()
if self._polling then
self:stopPolling()
else
self:startPolling()
end
end
function Plugin:stopPolling()
if not self._polling then
return
end
print("Stopping polling...")
self._polling = false
self._label.Enabled = false
end
function Plugin:startPolling()
if self._polling then
return
end
print("Starting to poll...")
self._polling = true
self._label.Enabled = true
return self:server()
:andThen(function(server)
self:syncIn():await()
local project = server:getInfo():await().project
while self._polling do
local changes = server:getChanges():await()
local routes = {}
for _, change in ipairs(changes) do
table.insert(routes, change.route)
end
local items = server:read(routes):await()
for index = 1, #routes do
local partitionName = routes[index][1]
local partition = project.partitions[partitionName]
local data = items[index]
local fullRoute = collectMatch(partition.target, "[^.]+")
write(game, fullRoute, data)
end
wait(Config.pollingRate)
end
end)
:catch(function()
self:stopPolling()
end)
end
function Plugin:syncIn()
print("Syncing from server...")
return self:server()
:andThen(function(server)
local project = server:getInfo():await().project
local readRoutes = {}
for name in pairs(project.partitions) do
table.insert(readRoutes, {name})
end
local items = server:read(readRoutes):await()
for index = 1, #readRoutes do
local partitionName = readRoutes[index][1]
local partition = project.partitions[partitionName]
local data = items[index]
local fullRoute = collectMatch(partition.target, "[^.]+")
write(game, fullRoute, data)
end
print("Sync successful!")
end)
end
return Plugin