mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-25 13:31:37 +00:00
Basic synchronization of edited objects
This commit is contained in:
parent
00b903e97c
commit
8729de1312
6 changed files with 148 additions and 34 deletions
|
|
@ -57,14 +57,35 @@ function ApiContext:connect()
|
||||||
|
|
||||||
self.serverId = body.serverId
|
self.serverId = body.serverId
|
||||||
self.connected = true
|
self.connected = true
|
||||||
|
|
||||||
return self:_retrieveMessages()
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ApiContext:_retrieveMessages()
|
function ApiContext:readAll()
|
||||||
if not self.connected then
|
if not self.connected then
|
||||||
return Promise.resolve()
|
return Promise.reject()
|
||||||
|
end
|
||||||
|
|
||||||
|
return Http.get(self.url .. "/read_all")
|
||||||
|
:andThen(function(response)
|
||||||
|
local body = response:json()
|
||||||
|
|
||||||
|
if body.serverId ~= self.serverId then
|
||||||
|
return Promise.reject("server changed ID")
|
||||||
|
end
|
||||||
|
|
||||||
|
self.messageCursor = body.messageCursor
|
||||||
|
|
||||||
|
return body.instances
|
||||||
|
end, function(err)
|
||||||
|
self.connected = false
|
||||||
|
|
||||||
|
return Promise.reject(err)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ApiContext:retrieveMessages()
|
||||||
|
if not self.connected then
|
||||||
|
return Promise.reject()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Http.get(self.url .. "/subscribe/" .. self.messageCursor)
|
return Http.get(self.url .. "/subscribe/" .. self.messageCursor)
|
||||||
|
|
@ -81,7 +102,7 @@ function ApiContext:_retrieveMessages()
|
||||||
|
|
||||||
self.messageCursor = body.messageCursor
|
self.messageCursor = body.messageCursor
|
||||||
|
|
||||||
return self:_retrieveMessages()
|
return self:retrieveMessages()
|
||||||
end, function(err)
|
end, function(err)
|
||||||
self.connected = false
|
self.connected = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
local Promise = require(script.Parent.Parent.modules.Promise)
|
|
||||||
|
|
||||||
local Config = require(script.Parent.Config)
|
local Config = require(script.Parent.Config)
|
||||||
local Http = require(script.Parent.Http)
|
|
||||||
local ApiContext = require(script.Parent.ApiContext)
|
local ApiContext = require(script.Parent.ApiContext)
|
||||||
|
|
||||||
local REMOTE_URL = ("http://localhost:%d"):format(Config.port)
|
local REMOTE_URL = ("http://localhost:%d"):format(Config.port)
|
||||||
|
|
@ -14,10 +11,59 @@ function Session.new()
|
||||||
|
|
||||||
setmetatable(self, Session)
|
setmetatable(self, Session)
|
||||||
|
|
||||||
local api = ApiContext.new(REMOTE_URL, function(message)
|
local created = {}
|
||||||
print("Got message:", message)
|
|
||||||
|
created["0"] = game:GetService("ReplicatedFirst")
|
||||||
|
|
||||||
|
local api
|
||||||
|
local function readAll()
|
||||||
|
print("Reading all...")
|
||||||
|
|
||||||
|
return api:readAll()
|
||||||
|
:andThen(function(instances)
|
||||||
|
for id, instance in pairs(instances) do
|
||||||
|
if id ~= "0" then
|
||||||
|
local existing = created[id]
|
||||||
|
if existing ~= nil then
|
||||||
|
pcall(existing.Destroy, existing)
|
||||||
|
end
|
||||||
|
|
||||||
|
local real = Instance.new(instance.className)
|
||||||
|
real.Name = instance.name
|
||||||
|
|
||||||
|
for key, value in pairs(instance.properties) do
|
||||||
|
real[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
created[id] = real
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for id, instance in pairs(instances) do
|
||||||
|
if id ~= "0" then
|
||||||
|
print("parent", created[id], created[tostring(instance.parent)])
|
||||||
|
created[id].Parent = created[tostring(instance.parent)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
api = ApiContext.new(REMOTE_URL, function(message)
|
||||||
|
print("got message", message)
|
||||||
|
|
||||||
|
if message.type == "InstanceChanged" then
|
||||||
|
print("Instance", message.id, "changed!")
|
||||||
|
readAll()
|
||||||
|
else
|
||||||
|
warn("Unknown message type " .. message.type)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
api:connect()
|
api:connect()
|
||||||
|
:andThen(readAll)
|
||||||
|
:andThen(function()
|
||||||
|
return api:retrieveMessages()
|
||||||
|
end)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,14 @@ use std::sync::{mpsc, Arc, RwLock, Mutex};
|
||||||
use id::{Id, get_id};
|
use id::{Id, get_id};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
Something,
|
InstanceChanged {
|
||||||
|
id: Id,
|
||||||
|
},
|
||||||
|
Error {
|
||||||
|
message: String
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
||||||
|
|
@ -7,51 +7,74 @@ use partition::Partition;
|
||||||
use rbx::RbxInstance;
|
use rbx::RbxInstance;
|
||||||
use session::SessionConfig;
|
use session::SessionConfig;
|
||||||
use vfs_session::{VfsSession, FileItem, FileChange};
|
use vfs_session::{VfsSession, FileItem, FileChange};
|
||||||
use message_session::MessageSession;
|
use message_session::{Message, MessageSession};
|
||||||
|
|
||||||
fn file_to_instances(file_item: &FileItem, partition: &Partition, output: &mut HashMap<Id, RbxInstance>, instances_by_route: &mut HashMap<FileRoute, Id>) -> Id {
|
fn file_to_instances(
|
||||||
|
file_item: &FileItem,
|
||||||
|
partition: &Partition,
|
||||||
|
output: &mut HashMap<Id, RbxInstance>,
|
||||||
|
instances_by_route: &mut HashMap<FileRoute, Id>,
|
||||||
|
) -> (Id, Vec<Id>) {
|
||||||
match file_item {
|
match file_item {
|
||||||
FileItem::File { contents, route } => {
|
FileItem::File { contents, route } => {
|
||||||
let mut properties = HashMap::new();
|
let mut properties = HashMap::new();
|
||||||
properties.insert("Value".to_string(), contents.clone());
|
properties.insert("Value".to_string(), contents.clone());
|
||||||
|
|
||||||
let primary_id = get_id();
|
let (primary_id, parent) = match instances_by_route.get(&file_item.get_route()) {
|
||||||
|
Some(&id) => {
|
||||||
|
(id, output.get(&id).unwrap().parent)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let id = get_id();
|
||||||
|
instances_by_route.insert(route.clone(), id);
|
||||||
|
|
||||||
instances_by_route.insert(route.clone(), primary_id);
|
(id, None)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
output.insert(primary_id, RbxInstance {
|
output.insert(primary_id, RbxInstance {
|
||||||
name: route.name(partition).to_string(),
|
name: route.name(partition).to_string(),
|
||||||
class_name: "StringValue".to_string(),
|
class_name: "StringValue".to_string(),
|
||||||
parent: None,
|
parent,
|
||||||
properties,
|
properties,
|
||||||
});
|
});
|
||||||
|
|
||||||
primary_id
|
(primary_id, vec![primary_id])
|
||||||
},
|
},
|
||||||
FileItem::Directory { children, route } => {
|
FileItem::Directory { children, route } => {
|
||||||
let primary_id = get_id();
|
let (primary_id, parent) = match instances_by_route.get(&file_item.get_route()) {
|
||||||
|
Some(&id) => {
|
||||||
|
(id, output.get(&id).unwrap().parent)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let id = get_id();
|
||||||
|
instances_by_route.insert(route.clone(), id);
|
||||||
|
|
||||||
instances_by_route.insert(route.clone(), primary_id);
|
(id, None)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
output.insert(primary_id, RbxInstance {
|
output.insert(primary_id, RbxInstance {
|
||||||
name: route.name(partition).to_string(),
|
name: route.name(partition).to_string(),
|
||||||
class_name: "Folder".to_string(),
|
class_name: "Folder".to_string(),
|
||||||
parent: None,
|
parent,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut changed_ids = vec![primary_id];
|
||||||
|
|
||||||
for child_file_item in children.values() {
|
for child_file_item in children.values() {
|
||||||
let mut child_instances = HashMap::new();
|
let (child_id, mut child_changed_ids) = file_to_instances(child_file_item, partition, output, instances_by_route);
|
||||||
let child_id = file_to_instances(child_file_item, partition, &mut child_instances, instances_by_route);
|
|
||||||
|
|
||||||
child_instances.get_mut(&child_id).unwrap().parent = Some(primary_id);
|
output.get_mut(&child_id).unwrap().parent = Some(primary_id);
|
||||||
|
|
||||||
for (instance_id, instance) in child_instances.drain() {
|
changed_ids.push(child_id);
|
||||||
output.insert(instance_id, instance);
|
for id in child_changed_ids.drain(..) {
|
||||||
|
changed_ids.push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
primary_id
|
(primary_id, changed_ids)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,6 +84,8 @@ pub struct RbxSession {
|
||||||
|
|
||||||
vfs_session: Arc<RwLock<VfsSession>>,
|
vfs_session: Arc<RwLock<VfsSession>>,
|
||||||
|
|
||||||
|
message_session: MessageSession,
|
||||||
|
|
||||||
/// The RbxInstance that represents each partition.
|
/// The RbxInstance that represents each partition.
|
||||||
partition_instances: HashMap<String, Id>,
|
partition_instances: HashMap<String, Id>,
|
||||||
|
|
||||||
|
|
@ -76,6 +101,7 @@ impl RbxSession {
|
||||||
RbxSession {
|
RbxSession {
|
||||||
config,
|
config,
|
||||||
vfs_session,
|
vfs_session,
|
||||||
|
message_session,
|
||||||
partition_instances: HashMap::new(),
|
partition_instances: HashMap::new(),
|
||||||
instances: HashMap::new(),
|
instances: HashMap::new(),
|
||||||
instances_by_route: HashMap::new(),
|
instances_by_route: HashMap::new(),
|
||||||
|
|
@ -92,12 +118,32 @@ impl RbxSession {
|
||||||
route: Vec::new(),
|
route: Vec::new(),
|
||||||
};
|
};
|
||||||
let file_item = vfs_session.get_by_route(&route).unwrap();
|
let file_item = vfs_session.get_by_route(&route).unwrap();
|
||||||
let root_id = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route);
|
let (root_id, _) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route);
|
||||||
self.partition_instances.insert(partition.name.clone(), root_id);
|
self.partition_instances.insert(partition.name.clone(), root_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_change(&mut self, change: &FileChange) {
|
pub fn handle_change(&mut self, change: &FileChange) {
|
||||||
println!("Handle RBX change {:?}", change);
|
let vfs_session_arc = self.vfs_session.clone();
|
||||||
|
let vfs_session = vfs_session_arc.read().unwrap();
|
||||||
|
|
||||||
|
match change {
|
||||||
|
FileChange::Created(route) | FileChange::Updated(route) => {
|
||||||
|
let file_item = vfs_session.get_by_route(route).unwrap();
|
||||||
|
let partition = self.config.partitions.get(&route.partition).unwrap();
|
||||||
|
let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route);
|
||||||
|
|
||||||
|
let messages = changed_ids
|
||||||
|
.iter()
|
||||||
|
.map(|&id| Message::InstanceChanged { id })
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
self.message_session.push_messages(&messages);
|
||||||
|
},
|
||||||
|
FileChange::Deleted(route) => {
|
||||||
|
},
|
||||||
|
FileChange::Moved(from_route, to_route) => {
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::thread;
|
||||||
use partition::Partition;
|
use partition::Partition;
|
||||||
use partition_watcher::PartitionWatcher;
|
use partition_watcher::PartitionWatcher;
|
||||||
use rbx_session::RbxSession;
|
use rbx_session::RbxSession;
|
||||||
use message_session::{MessageSession, Message};
|
use message_session::MessageSession;
|
||||||
use vfs_session::VfsSession;
|
use vfs_session::VfsSession;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -62,7 +62,6 @@ impl Session {
|
||||||
{
|
{
|
||||||
let vfs_session = self.vfs_session.clone();
|
let vfs_session = self.vfs_session.clone();
|
||||||
let rbx_session = self.rbx_session.clone();
|
let rbx_session = self.rbx_session.clone();
|
||||||
let message_session = self.message_session.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -77,8 +76,6 @@ impl Session {
|
||||||
let mut rbx_session = rbx_session.write().unwrap();
|
let mut rbx_session = rbx_session.write().unwrap();
|
||||||
rbx_session.handle_change(&change);
|
rbx_session.handle_change(&change);
|
||||||
}
|
}
|
||||||
|
|
||||||
message_session.push_messages(&[Message::Something]);
|
|
||||||
},
|
},
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,6 @@ impl VfsSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_change(&mut self, change: &FileChange) -> Option<()> {
|
pub fn handle_change(&mut self, change: &FileChange) -> Option<()> {
|
||||||
println!("Got file change {:?}", change);
|
|
||||||
|
|
||||||
match change {
|
match change {
|
||||||
FileChange::Created(route) | FileChange::Updated(route) => {
|
FileChange::Created(route) | FileChange::Updated(route) => {
|
||||||
let new_item = self.read(&route).ok()?;
|
let new_item = self.read(&route).ok()?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue