Table of Contents

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
Object
ScriptableObject
HousingSystem
Implements
IServerBehaviour<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>
IServerComponent<INetworkManagerWrapper, ServerManager, NetworkConnection, IServerBehaviour>
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.name
Object.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

bool

AllowsPlayerOwnership

True when an individual character may own land.

public bool AllowsPlayerOwnership { get; }

Property Value

bool

IsHousingEnabled

True when housing is enabled in any form.

public bool IsHousingEnabled { get; }

Property Value

bool

OwnershipMode

Who may own land and housing on this server.

public HousingOwnershipMode OwnershipMode { get; }

Property Value

HousingOwnershipMode

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

plotID long

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

plotID long

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

characterID long

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

player IPlayerCharacter
plot PlotFoundation
template PlotStructureTemplate
localPosition Vector3
yaw float
existingStructures IReadOnlyList<Bounds>

Returns

PlotPlacementResult

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

foundation PlotFoundation

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

player IPlayerCharacter
onFetched Action<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

player IPlayerCharacter
vaultID long

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

ServerComponentInitializationStatus

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

deltaTime float

RetrieveFromVault(IPlayerCharacter, long)

Buys one stored stack back out of the vault.

public void RetrieveFromVault(IPlayerCharacter player, long vaultID)

Parameters

player IPlayerCharacter
vaultID long

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

plotID long

The plot being taken back.

ownerCharacterID long

The 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

player IPlayerCharacter
foundation IPlotFoundation

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

player IPlayerCharacter
foundation IPlotFoundation

Returns

bool

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

player IPlayerCharacter
foundation IPlotFoundation

Returns

bool

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

granter IPlayerCharacter

The character handing out the access.

foundation IPlotFoundation

The plot in question.

targetCharacterID long

Who is being granted.

requested PlotPermission

What they are being given.

Returns

bool

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

revoker IPlayerCharacter
foundation IPlotFoundation
targetCharacterID long

Returns

bool

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.