Spaces:
Sleeping
Sleeping
| import { v } from 'convex/values'; | |
| import { defineTable } from 'convex/server'; | |
| import { serializedPlayer } from './player'; | |
| import { serializedPlayerDescription } from './playerDescription'; | |
| import { serializedAgent } from './agent'; | |
| import { serializedAgentDescription } from './agentDescription'; | |
| import { serializedWorld } from './world'; | |
| import { serializedWorldMap } from './worldMap'; | |
| import { serializedConversation } from './conversation'; | |
| import { conversationId, playerId } from './ids'; | |
| export const aiTownTables = { | |
| // This table has a single document that stores all players, conversations, and agents. This | |
| // data is small and changes regularly over time. | |
| worlds: defineTable({ ...serializedWorld }), | |
| // Worlds can be started or stopped by the developer or paused for inactivity, and this | |
| // infrequently changing document tracks this world state. | |
| worldStatus: defineTable({ | |
| worldId: v.id('worlds'), | |
| isDefault: v.boolean(), | |
| engineId: v.id('engines'), | |
| lastViewed: v.number(), | |
| status: v.union(v.literal('running'), v.literal('stoppedByDeveloper'), v.literal('inactive')), | |
| }).index('worldId', ['worldId']), | |
| // This table contains the map data for a given world. Since it's a bit larger than the player | |
| // state and infrequently changes, we store it in a separate table. | |
| maps: defineTable({ | |
| worldId: v.id('worlds'), | |
| ...serializedWorldMap, | |
| }).index('worldId', ['worldId']), | |
| // Human readable text describing players and agents that's stored in separate tables, just like `maps`. | |
| playerDescriptions: defineTable({ | |
| worldId: v.id('worlds'), | |
| ...serializedPlayerDescription, | |
| }).index('worldId', ['worldId', 'playerId']), | |
| agentDescriptions: defineTable({ | |
| worldId: v.id('worlds'), | |
| ...serializedAgentDescription, | |
| }).index('worldId', ['worldId', 'agentId']), | |
| //The game engine doesn't want to track players that have left or conversations that are over, since | |
| // it wants to keep its managed state small. However, we may want to look at old conversations in the | |
| // UI or from the agent code. So, whenever we delete an entry from within the world's document, we | |
| // "archive" it within these tables. | |
| archivedPlayers: defineTable({ worldId: v.id('worlds'), ...serializedPlayer }).index('worldId', [ | |
| 'worldId', | |
| 'id', | |
| ]), | |
| archivedConversations: defineTable({ | |
| worldId: v.id('worlds'), | |
| id: conversationId, | |
| creator: playerId, | |
| created: v.number(), | |
| ended: v.number(), | |
| lastMessage: serializedConversation.lastMessage, | |
| numMessages: serializedConversation.numMessages, | |
| participants: v.array(playerId), | |
| }).index('worldId', ['worldId', 'id']), | |
| archivedAgents: defineTable({ worldId: v.id('worlds'), ...serializedAgent }).index('worldId', [ | |
| 'worldId', | |
| 'id', | |
| ]), | |
| // The agent layer wants to know what the last (completed) conversation was between two players, | |
| // so this table represents a labelled graph indicating which players have talked to each other. | |
| participatedTogether: defineTable({ | |
| worldId: v.id('worlds'), | |
| conversationId, | |
| player1: playerId, | |
| player2: playerId, | |
| ended: v.number(), | |
| }) | |
| .index('edge', ['worldId', 'player1', 'player2', 'ended']) | |
| .index('conversation', ['worldId', 'player1', 'conversationId']) | |
| .index('playerHistory', ['worldId', 'player1', 'ended']), | |
| }; | |