resources

resources is a cursor rule for Cursor from thinktidevibes/2D-Survival-Multiplayer-Game. It costs 15 tokens per session (8,008 once invoked), scanned A, original, MIT.

A development guide for adding new resources, such as pumpkins or metal ore, and gatherable objects to a two-dimensional multiplayer survival game. It covers the required server data and logic, client state, images, and rendering changes.

In plain words
What is it for?
Use it when adding a new collectible item or resource node. It helps update server definitions, harvesting and respawning, generated bindings, client state, assets, and rendering.
Why use it?
Adding a resource affects many parts of a game, so missing one connection can make it fail to spawn, harvest, store, or display correctly. The guide provides a consistent sequence of changes.

Cursor rule for Cursor

Written for Cursor: installed under .cursor/.

Not installable on its own: it runs a file from its repository that does not travel with it. Clone the repository, or install whatever ships that file. The line is spacetime generate --lang typescript --out-dir ./client/src/generated --project-path ./server.

Install

Getting it into your agent

There is no command for this one: it runs only inside a plugin, and the catalogue could not identify which plugin ships it. The source is linked below.

Made for: Cursor.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for resources

README.md
[![agentmods](https://agentmods.dev/badge/rules/thinktidevibes/2d-survival-multiplayer-game/resources.svg)](https://agentmods.dev/rules/thinktidevibes/2d-survival-multiplayer-game/resources)
Your own site
<a href="https://agentmods.dev/rules/thinktidevibes/2d-survival-multiplayer-game/resources"><img src="https://agentmods.dev/badge/rules/thinktidevibes/2d-survival-multiplayer-game/resources.svg" alt="Measured on agentmods" height="20"></a>
Per session 15 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 8,008 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00015 $0.08008
Opus 5 $0.00008 $0.04004
Sonnet 5 $0.00003 $0.01602
Haiku 4.5 $0.00002 $0.00801

Measured 6d ago against content hash 1b8a0dfac499, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-06, from the pricing page.

Security

Grade A, and why

resources scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 6d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

.cursor/rules/resources.mdc · 520 lines

How it starts

The opening of the file, as written. The whole thing — 520 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Guide: Adding New Resources and Nodes

This guide outlines the steps required to add new consumable resources (like Pumpkins) or gatherable nodes (like Metal Ore) to the 2D Survival Multiplayer game. Follow these steps to ensure consistency with the existing architecture.

General Workflow

  1. Define Data (Server): Add necessary item definitions and entity table structures.
  2. Implement Logic (Server): Create server-side reducers for interaction, harvesting, spawning, and respawning.
  3. Integrate (Server): Update server logic (seeding, respawning) to include the new resource.
  4. Generate Bindings (CLI): Run spacetime generate before making client-side changes that depend on new server types or reducers.
  5. Add Assets (Client): Place images for the resource doodad and its corresponding item.
  6. Client-Side State Management:
    • Update useSpacetimeTables.ts to manage the new entity's state.
    • Update App.tsx to fetch and pass the new entity's data.
    • Update GameScreen.tsx to receive and pass down the new entity's data.
  7. Client Rendering & Logic (Client):
    • Create rendering utilities (e.g., pumpkinRenderingUtils.ts) including image preloading.
    • Update type guards (typeGuards.ts).
    • Update entity filtering (useEntityFiltering.ts).
    • Integrate into the main rendering loop (GameCanvas.tsx).
    • Update interaction finding (useInteractionFinder.ts).
    • Update interaction labels (labelRenderingUtils.ts).
    • Update input handling (useInputHandler.ts) to call server reducers.
    • Update item icon mapping (itemIconUtils.ts).
  8. Testing: Test spawning, interaction/harvesting, item yield, respawning, and UI rendering thoroughly.

Adding a Consumable Resource (e.g., Pumpkin)

This resource type is picked up directly by the player, disappears, and respawns after a timer. It yields an item (e.g., "Pumpkin" item).

Server (server/)

  1. Define Item:
    • In src/items_database.rs, within the get_item_definitions() function's returned vector, add an ItemDefinition for the yielded item (e.g., "Pumpkin").
      ItemDefinition {
          id: 0, // Will be auto-assigned
          name: "Pumpkin".to_string(),
          description: "A ripe pumpkin, good for eating or crafting.".to_string(),
          category: ItemCategory::Consumable, // Or ItemCategory::Material if not directly edible
          icon_asset_name: "pumpkin.png".to_string(), // Matches asset in client/src/assets/items/
          is_stackable: true,
          stack_size: 10,
          // ... other fields as necessary
          damage: None,
          is_equippable: false,
          equipment_slot_type: None,
          fuel_burn_duration_secs: None,
      }
      
  2. Create Resource Module:
    • Create a new file: src/pumpkin.rs.
  3. Define Entity Struct (src/pumpkin.rs):
    • Define the Pumpkin struct:
      use spacetimedb::{table, ReducerContext, Identity, Timestamp, log};
      use crate::collectible_resources::{validate_player_resource_interaction, collect_resource_and_schedule_respawn, BASE_RESOURCE_RADIUS, PLAYER_RESOURCE_INTERACTION_DISTANCE_SQUARED};
      use crate::TILE_SIZE_PX; // If needed for positioning logic, though not directly for basic consumable
      
      #[table(name = pumpkin, public)]
      #[derive(Clone, Debug)]
      pub struct Pumpkin {
          #[primary_key]
          #[auto_inc]
          pub id: u64,
          pub pos_x: f32,
          pub pos_y: f32,
          pub chunk_index: u32,
          pub respawn_at: Option<Timestamp>,
      }
      
      // Constants
      pub const PUMPKIN_YIELD_ITEM_NAME: &str = "Pumpkin"; // Name of the item defined in items_database.rs
      pub const PUMPKIN_YIELD_AMOUNT: u32 = 1;
      pub const PUMPKIN_RESPAWN_TIME_SECS: u64 = 180; // Example: 3 minutes
      pub const PUMPKIN_RADIUS: f32 = BASE_RESOURCE_RADIUS; // Or a custom radius
      
      // Spawning density and minimum distance constants (adjust as needed)
      pub const PUMPKIN_DENSITY_PERCENT: f32 = 0.5;
      pub const MIN_PUMPKIN_DISTANCE_SQ: f32 = (PUMPKIN_RADIUS * 2.0 + 50.0) * (PUMPKIN_RADIUS * 2.0 + 50.0);
      pub const MIN_PUMPKIN_TREE_DISTANCE_SQ: f32 = (PUMPKIN_RADIUS + crate::tree::TREE_RADIUS + 50.0) * (PUMPKIN_RADIUS + crate::tree::TREE_RADIUS + 50.0);
      pub const MIN_PUMPKIN_STONE_DISTANCE_SQ: f32 = (PUMPKIN_RADIUS + crate::stone::STONE_RADIUS + 50.0) * (PUMPKIN_RADIUS + crate::stone::STONE_RADIUS + 50.0);
      // Add similar constants for other resources if needed (e.g., MIN_PUMPKIN_CORN_DISTANCE_SQ)
      
  4. Implement Interaction Reducer (src/pumpkin.rs):
    • Create a reducer interact_with_pumpkin(ctx: &ReducerContext, pumpkin_id: u64).
      #[spacetimedb::reducer]
      pub fn interact_with_pumpkin(ctx: &ReducerContext, pumpkin_id: u64) -> Result<(), String> {
          let sender_id = ctx.sender;
      
          let pumpkin_entity = ctx.db.pumpkin().id().find(pumpkin_id)
              .ok_or_else(|| format!("Pumpkin with ID {} not found.", pumpkin_id))?;
      
          validate_player_resource_interaction(ctx, sender_id, pumpkin_entity.pos_x, pumpkin_entity.pos_y)?;
      
          if pumpkin_entity.respawn_at.is_some() {
              return Err("Pumpkin is not ready to be harvested.".to_string());
          }
      
          collect_resource_and_schedule_respawn(
              ctx,
              sender_id,
              pumpkin_id, // The ID of the pumpkin entity itself
              PUMPKIN_YIELD_ITEM_NAME.to_string(), // The *name* of the item to give
              PUMPKIN_YIELD_AMOUNT,
              PUMPKIN_RESPAWN_TIME_SECS,
              |db_pumpkin_table, id_to_update, respawn_timestamp| { // Closure to update the pumpkin table
                  if let Some(mut p) = db_pumpkin_table.id().find(id_to_update) {
                      p.respawn_at = Some(respawn_timestamp);
                      db_pumpkin_table.id().update(p);
                      Ok(())
                  } else {
                      Err(format!("Failed to find pumpkin {} to mark for respawn.", id_to_update))
                  }
              },
              |pumpkin_table_handle| pumpkin_table_handle.id() // Provide PK index accessor
          )?;
      
          log::info!("Player {} collected pumpkin {}", sender_id, pumpkin_id);
          Ok(())
      }
      
  5. Register Module (src/lib.rs):
    • Add mod pumpkin; to the module declarations.
    • Add use crate::pumpkin::pumpkin as PumpkinTableTrait; for the table trait import.
  6. Update Seeding (src/environment.rs):
    • Add use crate::pumpkin; and use crate::pumpkin::pumpkin as PumpkinTableTrait;.
    • In seed_environment:
      • Get the table accessor: let pumpkins = ctx.db.pumpkin();
      • Initialize a position vector: let mut spawned_pumpkin_positions: Vec<(f32, f32)> = Vec::new();
      • Calculate target_pumpkin_count using PUMPKIN_DENSITY_PERCENT.
      • Add a loop calling attempt_single_spawn, providing:
        • pumpkins table accessor.
        • spawned_pumpkin_positions.
        • PUMPKIN_RADIUS.
        • Pumpkin-specific distance constants (e.g., MIN_PUMPKIN_DISTANCE_SQ, MIN_PUMPKIN_TREE_DISTANCE_SQ).
        • A closure to create a crate::pumpkin::Pumpkin instance (with id: 0, pos_x, pos_y, chunk_index, respawn_at: None).
      • Update count_all_resources to include pumpkins.count() as i32.
  7. Update Respawning (src/environment.rs):
    • In check_resource_respawns, add a call to the check_and_respawn_resource! macro:
      check_and_respawn_resource!(
          ctx,
          pumpkin,                   // Table name (lowercase)
          crate::pumpkin::Pumpkin,   // Struct type
          "Pumpkin",                 // Log message name
          |_p: &crate::pumpkin::Pumpkin| true, // Condition to check if respawn_at is set
          |p: &mut crate::pumpkin::Pumpkin| { // Closure to reset respawn_at
              p.respawn_at = None;
          }
      );
      
  8. Add Consumable Effects (Optional - src/consumables.rs):
    • If "Pumpkin" item is directly edible:
      • Define constants like PUMPKIN_HEALTH_GAIN.
      • Update the consume_item reducer's match statement to handle "Pumpkin".

Read the full file on GitHub · 520 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 6d ago First seen · 520 lines · 15 tokens per session scan A 1b8a0dfac499

Subscribe to this mod's changes

resources is a cursor rule published in the GitHub repository thinktidevibes/2D-Survival-Multiplayer-Game (11 stars, last pushed 1y ago), licensed MIT. It adds 15 tokens to every session and 8,008 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.