cryptomax
cryptomax3mo ago

If two players request ownership at the same moment

Are there circumstances where it looks momentarily like you could own the item locally but then your ownership is rejected by the server?
17 Replies
kapa.ai
kapa.ai3mo ago
Hi @cryptomax. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Yes, there are circumstances where it may momentarily appear that you own an item locally, but then your ownership is rejected by the server. This can happen when two clients simultaneously request ownership of the same object. In NormalVR's Normcore, the RequestOwnership() and ClearOwnership() methods take effect immediately. However, if the server blocks the request—say, because preventOwnershipTakeover is true or because the view's parent is owned by another client—then ownership and all changes that required ownership will be rolled back.
// Mark the RealtimeView owned by the local client
myObjectView.RequestOwnership();

// Clear ownership of the RealtimeView
myObjectView.ClearOwnership();
// Mark the RealtimeView owned by the local client
myObjectView.RequestOwnership();

// Clear ownership of the RealtimeView
myObjectView.ClearOwnership();
Also, when using RealtimeModel objects, updates appear to take effect immediately for the local client. However, the server may reject an update due to either ownership or Normcore Private plug-ins. When this happens, the server sends back the rejected update or a modified version of the state in the update. The datastore then rolls the data back or replaces it with the version transformed by the server. In the case of RealtimeTransform, it is available for immediate use after RequestOwnership() is called. Normcore will assume the call is going to succeed, and will roll back any state changes automatically if the call is rejected by the server. A RequestOwnership() call is only rejected if the RealtimeView or a parent RealtimeView is owned by a different client. Sources: - RequestOwnership() + ClearOwnership() (https://normcore.io/documentation/room/ownership-and-lifetime-flags#requestownership--clearownership) - Instant updates (https://normcore.io/documentation/room/datastore#instant-updates) - RealtimeTransform > How it works (https://normcore.io/documentation/realtime/realtimetransform#how-it-works) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@401986039964631060> kapa.ai is still learning and improving, please let us know how it did by reacting below
cryptomax
cryptomax3mo ago
@Normcore Assistant does this mean in asituation where it is likely ownership is being requested at the same exact moment you can just wait a frame and check if it is owned locally?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can wait a frame and then check if the object is still owned locally. This is because Normcore handles ownership requests and updates immediately on the local client, but these changes might be rolled back in the next frame if the server rejects the ownership request. You can use the isOwnedLocallyInHierarchy property of the RealtimeView to check if the object is still owned locally. Here's an example of how you might do this in Unity:
IEnumerator CheckOwnershipNextFrame(RealtimeView realtimeView)
{
// Wait for the next frame
yield return null;

// Check if the object is still owned locally
if (realtimeView.isOwnedLocallyInHierarchy)
{
// The object is still owned locally
Debug.Log("Ownership confirmed");
}
else
{
// The object is not owned locally
Debug.Log("Ownership rejected");
}
}

// Usage
StartCoroutine(CheckOwnershipNextFrame(myRealtimeView));
IEnumerator CheckOwnershipNextFrame(RealtimeView realtimeView)
{
// Wait for the next frame
yield return null;

// Check if the object is still owned locally
if (realtimeView.isOwnedLocallyInHierarchy)
{
// The object is still owned locally
Debug.Log("Ownership confirmed");
}
else
{
// The object is not owned locally
Debug.Log("Ownership rejected");
}
}

// Usage
StartCoroutine(CheckOwnershipNextFrame(myRealtimeView));
Please note that this is a simplified example and actual usage may vary depending on your specific needs and the structure of your project. Sources: - Realtime > Common Questions (https://normcore.io/documentation/realtime/common-questions#i-have-a-script-on-my-player-why-is-it-updating-all-players-in-the-room) - RealtimeTransform > How it works (https://normcore.io/documentation/realtime/realtimetransform#how-it-works) - Datastore > Instant updates (https://normcore.io/documentation/room/datastore#instant-updates) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@401986039964631060> kapa.ai is still learning and improving, please let us know how it did by reacting below
cryptomax
cryptomax3mo ago
@Normcore Assistant What was hte difference between isOwnedLocallyInHierarchy and isOwnedLocallySelf?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The isOwnedLocallySelf and isOwnedLocallyInHierarchy properties are used to determine the ownership status of a component or model in Normcore. - isOwnedLocallySelf: This property returns true if the component or model is owned by the local client. It only checks the ownership of the specific component or model on which it is called. - isOwnedLocallyInHierarchy: This property returns true if the component or model or any of its parents in the hierarchy are owned by the local client. It checks the ownership of the entire hierarchy, from the specific component or model up to the root. In other words, isOwnedLocallySelf checks if the specific component or model is owned by the local client, while isOwnedLocallyInHierarchy checks if the specific component or model or any of its parent components or models are owned by the local client. Sources: - RealtimeModel > Properties Part 2 (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeModel) - RealtimeView > Properties Part 1 (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeView) - IRealtimeComponent (https://normcore.io/documentation/reference/classes/Normal.Realtime.IRealtimeComponent) - RealtimeComponent<TModel> (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeComponent%601) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@401986039964631060> kapa.ai is still learning and improving, please let us know how it did by reacting below
liamc
liamc3mo ago
Waiting one frame doesn't seem like a reliable solution since normcore only syncs at 20Hz. It won't sync changes every frame, so you'd need to wait until after the next normcore sync
cryptomax
cryptomax3mo ago
hmmm so you would subscribe to the write to know when that would be?
liamc
liamc3mo ago
Yeah, that'd be one way to do it. Or you could be lazy and wait 100ms or half a second 😛
cryptomax
cryptomax3mo ago
subscribing feels a little like over kill to solve the problelm since then forever you have 20 methods running per second that was really only to fix this tiny issue maybe better to just check if it's still unowned and tryagain? gues thats what your saying just wait longer
liamc
liamc3mo ago
If it's a common pattern you could have a single helper class to increment a counter after each write and just wait for the counter to change. Similar to Time.frameCount, but it'd be writeCount
Mechabit
Mechabit3mo ago
depending on what you need it for you can continue like it succeeded and poll the owner or use the ownerid changed event if it's for spawning stuff you can use the string key dictionary to be 100% sure only one message gets through
cryptomax
cryptomax3mo ago
was just handling losing ownership with a disconnected using ownership did change to check if it's unowned and then request onwership, but that means everyone would do iot, I geussI should just have only lowest connected request that would also handle it
Mechabit
Mechabit3mo ago
that would work
cryptomax
cryptomax3mo ago
wonder when that auto transfer to lowest connected might come about..... 🙂