Files
K-C-Multiplayer/CLAUDE.md
devbeni bd12485112 Add CLAUDE.md documentation for Claude Code
Provides architecture overview, packet system docs, and common patterns
for future development assistance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 10:49:52 +01:00

3.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a Kingdoms and Castles Multiplayer Mod that adds multiplayer functionality to the game using:

  • Riptide Networking library for low-level networking
  • Steam P2P transport for NAT traversal
  • Harmony for non-invasive game modification via patches/hooks

Architecture

Core Components

File Purpose
Main.cs Entry point, Harmony patches, all game event hooks
KCClient.cs Client-side networking wrapper around Riptide.Client
KCServer.cs Server-side networking, client management
KCPlayer.cs Player data container (id, steamId, inst, kingdomName)

Networking Layer

Riptide.Client/Server
    └── SteamClient/SteamServer (Steam P2P transport)
        └── KCClient/KCServer wrappers
            └── PacketHandler (serialization/routing)
  • Port: 7777, Max clients: 25
  • Team ID formula: clientId * 10 + 2

Packet System

Located in /Packets/:

  • Base class: Packet.cs with Send(), SendToAll(), HandlePacketClient(), HandlePacketServer()
  • PacketHandler.cs uses reflection for automatic serialization based on property names (alphabetical order)
  • Packet IDs defined in Enums/Packets.cs

Key packet ranges:

  • 25-34: Lobby (chat, player list, settings)
  • 70-79: World/building updates
  • 85: Save transfer (chunked)
  • 87-90: Building state, villagers

State Synchronization

  • Buildings: Observer pattern in StateManagement/BuildingState/ - monitors field changes every 100ms, sends updates every 300ms
  • Villagers: Event-based sync via Harmony hooks on VillagerSystem.AddVillager, Villager.TeleportTo
  • Save/Load: Custom MultiplayerSaveContainer extends LoadSaveContainer, stores per-player data

Harmony Hooks Pattern

All hooks check call stack to prevent infinite loops:

if (new StackFrame(3).GetMethod().Name.Contains("HandlePacket"))
    return; // Skip if called by network handler

Key Dictionaries

Main.kCPlayers        // Dictionary<steamId, KCPlayer>
Main.clientSteamIds   // Dictionary<clientId, steamId>

Common Issues & Patterns

Player Resolution

Main.GetPlayerByClientID(clientId)  // clientId -> KCPlayer
Main.GetPlayerByTeamID(teamId)      // teamId -> Player.inst
Main.GetPlayerByBuilding(building)  // building -> owner Player

Building Ownership

Buildings are associated with players via LandmassOwner.teamId. Use building.TeamID() to determine owner.

Save Directory

Multiplayer saves go to: Application.persistentDataPath + "/Saves/Multiplayer"

Directory Structure

/Attributes          - Custom packet attributes
/Enums              - Packet types, menu states
/LoadSaveOverrides  - MultiplayerSaveContainer
/Packets            - All network packets
/Riptide            - Networking library
/RiptideSteamTransport - Steam P2P adapter, LobbyManager
/StateManagement    - Observer pattern for sync
/ServerLobby        - Lobby UI
/ServerBrowser      - Server discovery
/UI                 - Custom UI elements

Known Architecture Limitations

  1. Static Client/Server instances can cause issues on reconnect
  2. Call stack checking for loop prevention is fragile
  3. No conflict resolution - last-write-wins
  4. Villager sync is event-based only, no continuous state updates