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']), | |
}; | |