Class HousingSystem
- Namespace
- FishMMO.Server.Implementation.World.SceneServer
- Assembly
- FishMMO.Server.dll
Who an owner has let into their plot, and putting out anybody who should not be in it.
[CreateAssetMenu(fileName = "HousingSystem", menuName = "FishMMO/Server/SceneServer/Housing System", order = 1)]
[RequiresDataContainer(typeof(HousingSystemMainThreadQueueData))]
[RequiresDataContainer(typeof(AsyncWorkerData))]
public class HousingSystem : ServerBehaviour, IServerBehaviour<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>, IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>, IHousingSystem, IServerBehaviour, IServerComponent
- Inheritance
-
ObjectScriptableObjectHousingSystem
- Implements
- Inherited Members
-
ScriptableObject.SetDirty()ScriptableObject.CreateInstance<T>()Object.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.ToString()Object.nameObject.hideFlags
Remarks
Houses are locked by default. Ownership admits its owner; everybody else needs a grant, and a grant is per plot rather than per player, so buying new land does not come with the guest list of the old.
Grants are only half of it. An access rule enforced at the doorway is a rule anybody already inside can ignore, and the two moments that matter most — a friend being revoked, and an owner starting work — both happen to people who are standing in the house at the time. The sweep in this file is what makes "may I be here" the same question as "may I come in".
Properties
AllowsGuildOwnership
True when a guild may own land.
public bool AllowsGuildOwnership { get; }
Property Value
AllowsPlayerOwnership
True when an individual character may own land.
public bool AllowsPlayerOwnership { get; }
Property Value
IsHousingEnabled
True when housing is enabled in any form.
public bool IsHousingEnabled { get; }
Property Value
OwnershipMode
Who may own land and housing on this server.
public HousingOwnershipMode OwnershipMode { get; }
Property Value
Methods
ClearAccessGrants(long)
Clears every grant on a plot, in the database and on every copy of it here.
public void ClearAccessGrants(long plotID)
Parameters
plotIDlong
Remarks
Run when a plot changes hands. A new owner must not inherit the last one's guest list, and an owner who reclaims land later must not find the people they evicted still holding keys.
ClearStructures(long)
Removes everything built on a plot, and forgets it.
public void ClearStructures(long plotID)
Parameters
plotIDlong
Remarks
Land that changes hands must not arrive with the last owner's house still on it. Called on release, and by reclamation when that lands.
EndBuildingFor(long)
Ends every session a character holds.
public void EndBuildingFor(long characterID)
Parameters
characterIDlong
Remarks
Called when a character leaves. Without it, logging out mid-build would leave the plot closed until the timeout, and the owner would come back to land they cannot enter.
EvaluatePlacement(IPlayerCharacter, PlotFoundation, PlotStructureTemplate, Vector3, float, IReadOnlyList<Bounds>)
Decides whether a structure may be placed, without writing anything.
public PlotPlacementResult EvaluatePlacement(IPlayerCharacter player, PlotFoundation plot, PlotStructureTemplate template, Vector3 localPosition, float yaw, IReadOnlyList<Bounds> existingStructures)
Parameters
playerIPlayerCharacterplotPlotFoundationtemplatePlotStructureTemplatelocalPositionVector3yawfloatexistingStructuresIReadOnlyList<Bounds>
Returns
Remarks
The server's answer, reached with the same shared code a client uses to grey out a placement before asking. Every check here is re-made server-side rather than trusted, because the client's copy of the plot's bounds, its owner, and what is already built on it are all things a modified client can lie about.
EvictTrespassers(PlotFoundation)
Pushes everybody who may not be in one plot back outside it.
public void EvictTrespassers(PlotFoundation foundation)
Parameters
foundationPlotFoundation
Remarks
The single-plot entry point, for the moments that cannot wait for the sweep — a friend being revoked while standing in the house, and a lot going from public ground to a building site under the people crossing it.
FetchVault(IPlayerCharacter, Action<List<PlotVaultData>, List<long>>)
Reads back everything a character is owed, with today's fee against each entry.
public void FetchVault(IPlayerCharacter player, Action<List<PlotVaultData>, List<long>> onFetched)
Parameters
playerIPlayerCharacteronFetchedAction<List<PlotVaultData>, List<long>>
Remarks
The quote is computed here, from the row, with the same arithmetic the charge uses. A UI that worked the fee out for itself would drift from what is actually taken the moment either side was changed, and the player would see the game charge more than it said.
ForfeitFromVault(IPlayerCharacter, long)
Gives up one stored stack permanently, for nothing.
public void ForfeitFromVault(IPlayerCharacter player, long vaultID)
Parameters
playerIPlayerCharactervaultIDlong
Remarks
Offered because the fee grows without limit, and a player who does not want a thing back should not be left with a row that gets more expensive forever. Nothing is charged and nothing is returned.
InitializeOnce()
Reports the configured ownership mode once at startup.
public override ServerComponentInitializationStatus InitializeOnce()
Returns
Remarks
Logged because housing being off is indistinguishable from housing being broken from the outside — a player who cannot claim a plot sees the same nothing either way. One line at startup makes the configured state answerable without reading the asset.
OnDeinitialize()
Releases the foundation subscriptions taken during initialization.
public override void OnDeinitialize()
Remarks
Unconditional, unlike the subscribe. The mode is read once at startup, but a static event outlives this object either way, and unsubscribing something that was never subscribed is free — where leaving a dead handler attached is a scene server that keeps answering claim requests after it has been torn down.
OnUpdate(float)
Runs queued main-thread work and retries any scene still waiting on its world server.
protected override void OnUpdate(float deltaTime)
Parameters
deltaTimefloat
RetrieveFromVault(IPlayerCharacter, long)
Buys one stored stack back out of the vault.
public void RetrieveFromVault(IPlayerCharacter player, long vaultID)
Parameters
playerIPlayerCharactervaultIDlong
Remarks
The money goes first here, which is the opposite of how a plot is claimed — and for the same underlying reason. A plot is contended, so the contended step goes first and losing costs nothing. A vault row is contended by nobody but its owner: the only race is the player clicking twice, and the removal is what settles that. So the order is charge, then remove, then hand over.
The failure that order admits is being charged for a row that had already gone, which is why the removal's row count is checked and the fee refunded when it comes back zero. The opposite order admits losing the furniture for free, which cannot be undone at all.
StoreContentsInVault(long, long)
Moves everything on a plot into its owner's vault, then leaves the land bare.
public void StoreContentsInVault(long plotID, long ownerCharacterID)
Parameters
plotIDlongThe plot being taken back.
ownerCharacterIDlongThe owner losing it, or zero for guild-owned land.
Remarks
Replaces the outright demolition reclamation used to do. Guild-owned land still has no vault to move anything into — there is no guild that owns a container — so it falls back to clearing, and says so rather than failing quietly.
TryBeginBuilding(IPlayerCharacter, IPlotFoundation)
Opens a build session on a plot, if the character may edit it.
public bool TryBeginBuilding(IPlayerCharacter player, IPlotFoundation foundation)
Parameters
playerIPlayerCharacterfoundationIPlotFoundation
Returns
- bool
True when the session is now open and held by this character.
TryEndBuilding(IPlayerCharacter, IPlotFoundation)
Closes a build session.
public bool TryEndBuilding(IPlayerCharacter player, IPlotFoundation foundation)
Parameters
playerIPlayerCharacterfoundationIPlotFoundation
Returns
Remarks
Closing somebody else's session is refused rather than ignored, so a stray message cannot unlock a plot mid-edit and drop other players into it.
TryFinishBuilding(IPlayerCharacter, IPlotFoundation)
Declares a house finished, moving the plot from building to occupied.
public bool TryFinishBuilding(IPlayerCharacter player, IPlotFoundation foundation)
Parameters
playerIPlayerCharacterfoundationIPlotFoundation
Returns
Remarks
An explicit step rather than something inferred from the first structure being placed. The two states differ in who may come in — building admits only the owner, occupied admits their friends — and that is a decision the owner should make when they are ready, not one the game makes for them the moment they put down a wall.
Closing the build session first is deliberate. The session is the tighter lock, and leaving it open would move the plot to occupied while still turning every guest away — which reads as the state change having silently failed.
TryGrantAccess(IPlayerCharacter, IPlotFoundation, long, PlotPermission)
Grants or narrows one character's access to a plot.
public bool TryGrantAccess(IPlayerCharacter granter, IPlotFoundation foundation, long targetCharacterID, PlotPermission requested)
Parameters
granterIPlayerCharacterThe character handing out the access.
foundationIPlotFoundationThe plot in question.
targetCharacterIDlongWho is being granted.
requestedPlotPermissionWhat they are being given.
Returns
Remarks
Clamped to what the granter holds themselves, so a friend with InviteFriends cannot mint permissions the owner never gave them. Without that the model collapses to its weakest link: whoever can invite can invite themselves into everything.
TryRevokeAccess(IPlayerCharacter, IPlotFoundation, long)
Takes away one character's access to a plot, and puts them out if they are standing in it.
public bool TryRevokeAccess(IPlayerCharacter revoker, IPlotFoundation foundation, long targetCharacterID)
Parameters
revokerIPlayerCharacterfoundationIPlotFoundationtargetCharacterIDlong
Returns
Remarks
The eviction is the point. A revocation that only closed the door would leave the revoked friend exactly where they were, free to stay as long as they did not walk out — and free to log out there and come back to it later.