Track item updatedBy as readonly metadata and inspect field

This commit is contained in:
Jage9
2026-02-27 02:27:16 -05:00
parent ac88195c6e
commit 4fcd006856
12 changed files with 35 additions and 4 deletions

View File

@@ -86,6 +86,7 @@ GLOBAL_ITEM_PROPERTY_METADATA: dict[str, dict[str, object]] = {
"carrierId": {"valueType": "text", "tooltip": "User id currently carrying this item, or none.", "label": "Carrier"},
"version": {"valueType": "number", "tooltip": "Server-side item version incremented on each update.", "label": "Version"},
"createdBy": {"valueType": "text", "tooltip": "Username that originally created this item.", "label": "Created by"},
"updatedBy": {"valueType": "text", "tooltip": "Username that most recently updated this item.", "label": "Updated by"},
"createdAt": {"valueType": "text", "tooltip": "Creation timestamp for this item.", "label": "Created at"},
"updatedAt": {"valueType": "text", "tooltip": "Last update timestamp for this item.", "label": "Updated at"},
"capabilities": {"valueType": "text", "tooltip": "Supported actions for this item type.", "label": "Capabilities"},

View File

@@ -46,6 +46,7 @@ class ItemService:
x=client.x,
y=client.y,
createdBy=client.username or client.nickname or client.id,
updatedBy=client.username or client.nickname or client.id,
createdAt=now,
updatedAt=now,
version=1,
@@ -90,6 +91,7 @@ class ItemService:
item.x = client.x
item.y = client.y
item.updatedAt = self.now_ms()
item.updatedBy = "system"
changed.append(item)
return changed
@@ -115,6 +117,7 @@ class ItemService:
x=persisted.x,
y=persisted.y,
createdBy=persisted.createdBy,
updatedBy=persisted.updatedBy or persisted.createdBy,
createdAt=persisted.createdAt,
updatedAt=persisted.updatedAt,
version=persisted.version,
@@ -168,6 +171,7 @@ class ItemService:
x=item.x,
y=item.y,
createdBy=item.createdBy,
updatedBy=item.updatedBy,
createdAt=item.createdAt,
updatedAt=item.updatedAt,
version=item.version,

View File

@@ -243,6 +243,7 @@ class WorldItem(BaseModel):
x: int
y: int
createdBy: str
updatedBy: str
createdAt: int
updatedAt: int
version: int
@@ -262,6 +263,7 @@ class PersistedWorldItem(BaseModel):
x: int
y: int
createdBy: str
updatedBy: str | None = None
createdAt: int
updatedAt: int
version: int

View File

@@ -387,6 +387,7 @@ class SignalingServer:
"carrierId": item.carrierId or "none",
"version": str(item.version),
"createdBy": item.createdBy,
"updatedBy": item.updatedBy,
"createdAt": self._format_display_timestamp_ms(item.createdAt),
"updatedAt": self._format_display_timestamp_ms(item.updatedAt),
"capabilities": ", ".join(item.capabilities) if item.capabilities else "none",
@@ -399,6 +400,12 @@ class SignalingServer:
return item.model_copy(update={"display": self._build_item_display_values(item)})
@staticmethod
def _item_updated_by_actor(client: ClientConnection) -> str:
"""Resolve display name stored in `updatedBy` for client-initiated item mutations."""
return client.username or client.nickname or client.id
def _get_item_emit_range(self, item: WorldItem) -> int:
"""Return effective emit range for one item with sane bounds."""
@@ -474,6 +481,7 @@ class SignalingServer:
item.params["stationName"] = station_name
item.params["nowPlaying"] = now_playing
item.updatedAt = self.item_service.now_ms()
item.updatedBy = "system"
item.version += 1
self._request_state_save()
await self._broadcast_item(item)
@@ -808,15 +816,16 @@ class SignalingServer:
"events": compact_events,
}
self.item_service.save_piano_songs()
owner_id = str(session.get("ownerClientId", ""))
owner = self._get_client_by_id(owner_id) if owner_id else None
item.params["songId"] = song_id
item.params.pop("recording", None)
item.params.pop("recordingLengthMs", None)
item.updatedAt = self.item_service.now_ms()
item.updatedBy = owner.username if owner and owner.username else "system"
item.version += 1
self._request_state_save()
await self._broadcast_item(item)
owner_id = str(session.get("ownerClientId", ""))
owner = self._get_client_by_id(owner_id) if owner_id else None
if owner and notify_owner:
await self._send_piano_status(
owner,
@@ -1514,6 +1523,7 @@ class SignalingServer:
carried.x = client.x
carried.y = client.y
carried.updatedAt = self.item_service.now_ms()
carried.updatedBy = self._item_updated_by_actor(client)
await self._broadcast_item(carried)
return
@@ -1549,6 +1559,7 @@ class SignalingServer:
carried.x = client.x
carried.y = client.y
carried.updatedAt = self.item_service.now_ms()
carried.updatedBy = self._item_updated_by_actor(client)
await self._broadcast_item(carried)
await self._broadcast(
BroadcastTeleportCompletePacket(
@@ -1725,6 +1736,7 @@ class SignalingServer:
item.x = client.x
item.y = client.y
item.updatedAt = self.item_service.now_ms()
item.updatedBy = self._item_updated_by_actor(client)
await self._broadcast_item(item)
self._request_state_save()
await self._send_item_result(client, True, "pickup", f"Picked up {item.title}.", item.id)
@@ -1745,6 +1757,7 @@ class SignalingServer:
item.x = packet.x
item.y = packet.y
item.updatedAt = self.item_service.now_ms()
item.updatedBy = self._item_updated_by_actor(client)
await self._broadcast_item(item)
self._request_state_save()
await self._send_item_result(client, True, "drop", f"Dropped {item.title}.", item.id)
@@ -1824,6 +1837,7 @@ class SignalingServer:
await self._send_item_result(client, False, "use", str(exc), item.id)
return
item.updatedAt = now_ms
item.updatedBy = self._item_updated_by_actor(client)
self._request_state_save()
await self._broadcast_item(item)
@@ -1900,6 +1914,7 @@ class SignalingServer:
await self._send_item_result(client, False, "secondary_use", str(exc), item.id)
return
item.updatedAt = self.item_service.now_ms()
item.updatedBy = self._item_updated_by_actor(client)
item.version += 1
self._request_state_save()
await self._broadcast_item(item)
@@ -2074,6 +2089,7 @@ class SignalingServer:
return
item.params = next_params
item.updatedAt = self.item_service.now_ms()
item.updatedBy = self._item_updated_by_actor(client)
item.version += 1
await self._broadcast_item(item)
self._request_state_save()