跳到正文

sim-chat

作者:Yarden-zamir

A chatclient inside minecraft with databack driven simulated conversations and dialog

收藏

介绍

中文介绍正在准备中,下面暂时显示原文。

Sim Chat

A Minecraft Forge mod that adds a slack/discord-style chat interface for dialogues. Designed for modpack creators to script conversations via datapacks and commands.

Features

  • Slack/Discord-style UI: Sidebar with conversation list, chat history panel with message bubbles
  • Team-based conversations: Players share conversation history within their team
  • Datapack-driven dialogues: Define dialogue trees in JSON, loaded as datapack resources
  • Action buttons: Clickable response options that trigger commands or continue dialogue
  • Conditional actions: Show/hide buttons based on data, scores, or KubeJS callbacks
  • Template system: Dynamic text with player names, team data, world info
  • Typing indicators: Simulated typing delay before messages appear
  • Toast notifications: Non-intrusive popups when new messages arrive
  • Custom avatars: Load PNG images from config folder for sender portraits
  • Team data storage: Store values, states, and scores per-team
  • KubeJS integration: Register custom callbacks for conditions and templates
  • SQLite storage: Persistent message history with lazy loading for large conversations
  • Scalable: Handles 100k+ messages with smooth scrolling and instant UI response

Dependencies

  • Requires the sqlite_jdbc library mod (minecraft-sqlite-jdbc) on both client and server

Storage

Conversation history is stored in a SQLite database at <world>/data/simchat/simchat.db. This provides:

  • Scalability: Handles 100k+ messages efficiently with lazy loading
  • Persistence: Data survives server restarts and world reloads
  • Inspectability: Messages stored as human-readable JSON (viewable in any SQLite browser)

Commands

Basic Commands

/simchat send <player> <dialogueId>    - Send dialogue to player
/simchat system <player> <entityId> <message>  - Send system message
/simchat clear <player> [entityId]     - Clear chat history
/simchat open <player> [entityId]      - Open chat screen for player
/simchat openmessage <messageId>       - Open chat to a specific message
/simchat reload                        - Reload KubeJS callbacks

Team Commands

/simchat team create <name>            - Create a new team
/simchat team invite [player]          - Invite player (or broadcast to all if omitted)
/simchat team join <teamId>            - Join a team by ID
/simchat team list                     - List all teams
/simchat team info                     - Show current team info
/simchat team title <newTitle>         - Change team name
/simchat team color <color>            - Change team color (name only)

Available colors: black, dark_blue, dark_green, dark_aqua, dark_red, dark_purple, gold, gray, dark_gray, blue, green, aqua, red, light_purple, yellow, white

Data Commands

Store values per-team for tracking progress, scores, states. All commands accept an optional [target] parameter (player name or team ID/title) to operate on a specific team:

/simchat data get <key> [target]       - Get value
/simchat data set <key> <value> [target]   - Set value (auto-detects numbers)
/simchat data add <key> <amount> [target]  - Add to numeric value
/simchat data remove <key> [target]    - Remove key
/simchat data list [target]            - List all data

Examples:

/simchat data get gold                 - Get your team's gold
/simchat data get gold Steve           - Get Steve's team's gold
/simchat data set rank vip "Team Alpha"    - Set string on Team Alpha
/simchat data set gold 100             - Set number (auto-detected)
/simchat data add points 10 abc1234    - Add 10 points to team abc1234

Callback Commands

/simchat callback list                 - List registered KubeJS callbacks
/simchat callback run <name> [player]  - Execute callback and show result

Datapack Format

Dialogues are loaded from: data/<namespace>/simchat/<path>.json

Example: data/mypack/simchat/contractor/greeting.json

{
  "entityId": "contractor",
  "entityName": "Director Vex",
  "entitySubtitle": "Helion Industries",
  "text": "Hello {player:name}! Your team ({team:title}) has completed {data:contracts_done} contracts.",
  "actions": [
    {
      "label": "Accept Contract (+{data:reward} credits)",
      "commands": [
        "simchat data add contracts_done 1",
        "give @s emerald 10"
      ],
      "reply": "I'll take the job.",
      "nextState": "mypack:contractor/contract_details",
      "condition": "data:has_clearance"
    },
    {
      "label": "Decline",
      "reply": "Not interested.",
      "condition": "!data:forced_contract"
    }
  ]
}

Dialogue Fields

| Field | Type | Description |
|——-|——|————-|
| entityId | string | Unique entity identifier (used for avatar lookup and conversation grouping) |
| entityName | string | Display name shown in chat |
| entitySubtitle | string | Optional subtitle (company, title) |
| text | string | Message content (supports templates) |
| actions | array | Response buttons (optional) |

Action Fields

| Field | Type | Description |
|——-|——|————-|
| label | string | Button text (supports templates) |
| commands | array | Commands to run when clicked |
| reply | string | Player’s reply shown in chat (supports templates) |
| nextState | string | Dialogue ID to trigger after this action |
| condition | string | Condition that must be true to show button |
| itemsVisual | array | Items to display on button |
| itemsInput | array | Items required from player (checked before enabling) |
| itemsOutput | array | Items given to player |

Item Format

{
  "item": "minecraft:diamond",
  "count": 5
}

Templates

Templates work in entityName, entitySubtitle, text, label, reply, and commands.

Prefix with {compile:...} (default) to resolve on the server when the message is created, or {runtime:...} to resolve on the client when the message is displayed. Runtime templates are stored and resolved client-side; the server only sees the compiled text. Runtime values refresh when the chat opens, when new messages arrive, or via the Refresh button.

Use {resolver:name} syntax in text, labels, and replies:

| Template | Description | Example |
|———-|————-|———|
| {player:name} | Player’s username | “Steve” |
| {player:uuid} | Player’s UUID | “069a79f4…” |
| {team:id} | Team ID | “a1b2c3d” |
| {team:title} | Team name | “The Builders” |
| {team:memberCount} | Number of team members | “3” |
| {team:color} | Team color name | “dark_blue” |
| {data:keyname} | Team data value | “42” |
| {world:day} | Current world day | “15” |
| {world:time} | Time of day (0-24000) | “6000” |
| {world:dimension} | Dimension ID | “minecraft:overworld” |
| {world:weather} | Weather state | “clear”, “rain”, “thunder” |
| {kjs:callbackName} | KubeJS callback result | (any value) |

Example:

{
  "text": "Day {world:day}: Hello {player:name}! You have {data:points} points."
}

Conditions

Use conditions to show/hide action buttons. Prefix with ! to negate.

| Condition | Description |
|———–|————-|
| data:keyname | True if team data is truthy (exists, non-zero, non-empty) |
| kjs:callbackName | True if KubeJS callback returns truthy |
| score:objectiveName | True if player’s scoreboard score > 0 |
| permission:level | True if player has permission level |

Examples:

{
  "actions": [
    {
      "label": "VIP Option",
      "condition": "data:is_vip"
    },
    {
      "label": "Regular Option",
      "condition": "!data:is_vip"
    },
    {
      "label": "Admin Only",
      "condition": "permission:2"
    }
  ]
}

KubeJS Integration

Register callbacks in kubejs/server_scripts/simchat.js:

// Clear old callbacks on reload
SimChat.clearCallbacks()

// Register a condition callback
SimChat.registerCallback('hasEnoughGold', ctx => {
    return ctx.player.persistentData.getInt('gold') >= 100
})

// Register a template callback
SimChat.registerCallback('goldAmount', ctx => {
    return ctx.player.persistentData.getInt('gold')
})

// Register using team data
SimChat.registerCallback('isVeteran', ctx => {
    return ctx.team && ctx.team.data.missions_completed >= 10
})

// Time-based callback
SimChat.registerCallback('greeting', ctx => {
    let time = ctx.player.level.dayTime % 24000
    if (time < 6000) return 'Good morning'
    if (time < 12000) return 'Good afternoon'
    return 'Good evening'
})

SimChat.logStatus() // Log callback count

Callback Context

Available in callbacks via ctx:

// Player (KubeJS wrapped - full access)
ctx.player
ctx.player.persistentData
ctx.player.level.dayTime
ctx.player.inventory

// Team (null if no team)
ctx.team.id
ctx.team.title
ctx.team.memberCount
ctx.team.data           // Map of all team data
ctx.team.data.keyname   // Access specific key
ctx.team.hasData('key') // Boolean check

// Entity (null if no entity context)
ctx.entity.id
ctx.entity.displayName
ctx.entity.messageCount
ctx.entity.lastMessage
ctx.entity.isTyping

Usage in Dialogues

{
  "text": "{kjs:greeting}, {player:name}! You have {kjs:goldAmount} gold.",
  "actions": [
    {
      "label": "Buy Item (100 gold)",
      "condition": "kjs:hasEnoughGold",
      "commands": ["simchat data add purchases 1"]
    }
  ]
}

Entity Files

Place entity configs and avatars in: config/simchat/entities/

Each entity can have:

  • <entityId>.json – Config with name, subtitle, avatar settings
  • <entityId>.png – Avatar image (any size, displayed at 36×36)

Example: config/simchat/entities/merchant.json

{
  "name": "Merchant Bob",
  "subtitle": "Ironwood Trading Co.",
  "avatar": "merchant"
}

| Field | Description |
|——-|————-|
| name | Default display name |
| subtitle | Default subtitle |
| avatar | Avatar ID (defaults to entityId) |

Defaults

Create default.json and/or default.png as fallbacks for entities without specific files.

All entity files hot-reload when modified.

Configuration

Client Config (simchat-client.toml)

| Option | Default | Description |
|——–|———|————-|
| notificationSound | minecraft:block.note_block.bell | Sound on new message |
| notificationVolume | 0.5 | Sound volume (0.0-1.0) |
| showToasts | true | Show toast popups |
| toastDuration | 5.0 | Toast display time (seconds) |
| sidebarWidth | 240 | Conversation list width |
| sidebarSortMode | 0 | Sort: 0=recent, 1=alphabetical |
| chatBackgroundColor | 0xDD12121F | Chat panel background (ARGB hex) |
| lazyLoadBatchSize | 30 | Messages to request when scrolling up |
| lazyLoadThreshold | 100 | Pixels from top before loading older messages |
| closedCacheSize | 400 | Messages to keep cached per conversation when chat closes |

Common Config (simchat-common.toml)

| Option | Default | Description |
|——–|———|————-|
| minDelay | 0.3 | Minimum typing delay (seconds) |
| maxDelay | 3.0 | Maximum typing delay (seconds) |
| charsPerSecond | 100.0 | Simulated typing speed |
| permissions.* | 4 | Per-command permission levels (0-4) |
| permissions.openmessage | 0 | Allow opening message links |
| teamJoin.joinBehavior | join_largest | join_largest, join_smallest, join_random, create_new |
| teamJoin.joinSizeCap | -1 | Auto-join cap (-1 disables, creates new if none eligible) |
| initialMessageCount | 30 | Messages per conversation on initial sync |
| maxLazyLoadBatchSize | 100 | Server-side cap for lazy load requests |

Color Overrides (simchat-client.toml)

Color settings live under the [colors] section and accept ARGB hex strings (e.g. 0xFF88AAFF). Example:

[ui]
chatBackgroundColor = "0x8047BAFF"

[colors]
sidebarBackgroundColor = "0xFF1B2230"
headerTextColor = "0xFFBBD7FF"
messageTextColor = "0xFFE8F1FF"
contextMenuBgColor = "0xFF202030"
toastBackgroundColor = "0xFF243048"

Available color keys (all optional):

  • sidebarBackgroundColor
  • dividerColor
  • dividerHoverColor
  • headerTextColor
  • headerSubtitleColor
  • emptyStateTextColor
  • headerSeparatorColor
  • refreshButtonColor
  • refreshButtonHoverColor
  • refreshTextColor
  • sortButtonColor
  • sortButtonHoverColor
  • sortTextColor
  • compactHintColor
  • scrollbarColor
  • inputBgColor
  • outputBgColor
  • disabledBgColor
  • playerNameColor
  • entityNameColor
  • subtitleColor
  • dayTextColor
  • messageTextColor
  • disabledTextColor
  • whiteTextColor
  • systemTextColor
  • buttonDefaultColor
  • buttonHoverColor
  • borderDisabledColor
  • borderHoverColor
  • borderDefaultColor
  • focusBorderColor
  • contextMenuBgColor
  • contextMenuBorderColor
  • contextMenuTextColor
  • contextMenuHighlightColor
  • inputValidColor
  • inputInvalidColor
  • inputFieldBgColor
  • inputFieldBorderColor
  • inputFieldBorderFocusedColor
  • inputCursorColor
  • inputSendEnabledColor
  • inputSendDisabledColor
  • toastSenderColor
  • toastPreviewColor
  • toastBackgroundColor
  • toastBorderColor
  • toastHintColor

Keybinds

| Key | Action |
|—–|——–|
| ; (semicolon) | Open chat screen |

JSON Schema

Validate your dialogues with the JSON schema at schemas/dialogue.schema.json.

VS Code setup:

{
  "$schema": "https://raw.githubusercontent.com/YardenZamir/sim-chat/main/schemas/dialogue.schema.json",
  "entityId": "...",
  ...
}

License

MIT

常见问题

sim-chat 支持哪些 Minecraft 版本?

sim-chat 支持 Minecraft Java 版 1.20.1,可用的加载器:Forge。下载时注意选择和你游戏版本一致的文件。

sim-chat 怎么安装?

先用 PCL2 或 HMCL 启动器安装对应版本的 Forge,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。运行环境:客户端和服务端都要装。

评论

登录后评论和评分

Yarden-zamir 的其他作品

查看全部 →