godot-genre-sandbox
Expert blueprint for sandbox games (Minecraft, Terraria, Garry's Mod) with physics-based interactions, cellular automata, emergent gameplay, and creative tools. Use when building open-world creation games with voxels, element systems, player-created structures, or procedural worlds. Keywords voxel, sandbox, cellular automata, MultiMesh, chunk management, emergent behavior, creative mode.
What this skill does
# Genre: Sandbox
Physical simulation, emergent play, and player creativity define this genre.
## NEVER Do (Expert Anti-Patterns)
### Performance & Scalability
- NEVER use individual `RigidBody` nodes for every block; strictly use **Static Colliders** for the world and reserve physics for dynamic props.
- NEVER simulate the entire world every frame; strictly process **"Dirty" chunks** with active changes. Sleeping chunks must consume zero CPU.
- NEVER update `MultiMesh` buffers every frame; strictly **batch changes** and only rebuild the buffer when a modification completes (e.g., player stops painting).
- NEVER use standard Godot `Nodes` for every grid cell; strictly use **PackedInt32Arrays** or typed Dictionaries to keep RAM overhead minimal.
- NEVER raycast against every individual voxel for placement; strictly use **Grid Quantization** (`floor(pos/size)`) for direct O(1) cell calculation.
- NEVER render every block face in a chunk; strictly generate an `ArrayMesh` that only pushes **visible exterior faces** to the GPU (Culling/Greedy Meshing).
### Data & Persistence
- NEVER save raw arrays of every block transform; strictly use **Run-Length Encoding (RLE)** (e.g., "Air x 50,000") to compress uniform spaces.
- NEVER load massive terrain chunks synchronously; strictly use `ResourceLoader.load_threaded_request()` to prevent frame stutter.
- NEVER use standard text `.tscn` files for voxel datasets; strictly use **binary `.res` files** for 10x faster parsing.
- NEVER ignore **Floating-Point Precision limits** (32,768 units); strictly implement floating-origin shifting for massive worlds.
### Systems & Architecture
- NEVER hardcode element interactions (`if water and fire`); strictly use a **Property System** where interactions emerge from material attributes (flammability, density).
- NEVER trust client-side placement in multiplayer; strictly require the **Server to validate** bounds and resources.
- NEVER manipulate the SceneTree from background generation threads; strictly use `call_deferred()` or Mutex locks for safety.
- NEVER leave orphaned chunks in memory; strictly track loaded regions and call `queue_free()` on discarded branches.
---
## ๐ Expert Components (scripts/)
### Original Expert Patterns
- [voxel_chunk_manager.gd](scripts/voxel_chunk_manager.gd) - Professional chunk management using `MultiMeshInstance3D` with batch update logic.
- [cellular_automata_liquid.gd](scripts/cellular_automata_liquid.gd) - Optimized simulation of liquids and powders using property-based density checks.
- [voxel_world.gd](scripts/voxel_world.gd) - Top-level world controller for grid state, tool-based editing, and chunk lifecycle.
### Modular Components
- [sandbox_patterns.gd](scripts/sandbox_patterns.gd) - Utility collection for async chunk loading, multithreading, and origin shifting.
## Architecture Patterns
### 1. Element System (Property-Based Emergence)
Model material properties, not behaviors. Interactions emerge from overlapping properties.
```gdscript
# element_data.gd
class_name ElementData extends Resource
enum Type { SOLID, LIQUID, GAS, POWDER }
@export var id: String = "air"
@export var type: Type = Type.GAS
@export var density: float = 0.0 # For liquid flow direction
@export var flammable: float = 0.0 # 0-1: Chance to ignite
@export var ignition_temp: float = 400.0
@export var conductivity: float = 0.0 # For electricity/heat
@export var hardness: float = 1.0 # Mining time multiplier
# EDGE CASE: What if two elements have same density but different types?
# SOLUTION: Use secondary sort (type enum priority: SOLID > LIQUID > POWDER > GAS)
func should_swap_with(other: ElementData) -> bool:
if density == other.density:
return type > other.type # Enum comparison: SOLID(0) > GAS(3)
return density > other.density
```
### 2. Cellular Automata Grid (Falling Sand Simulation)
Update order matters. Top-down prevents "teleporting" godot-particles.
```gdscript
# world_grid.gd
var grid: Dictionary = {} # Vector2i -> ElementData
var dirty_cells: Array[Vector2i] = []
func _physics_process(_delta: float) -> void:
# CRITICAL: Sort top-to-bottom to prevent double-moves
dirty_cells.sort_custom(func(a, b): return a.y < b.y)
for pos in dirty_cells:
simulate_cell(pos)
dirty_cells.clear()
func simulate_cell(pos: Vector2i) -> void:
var cell = grid.get(pos)
if not cell: return
match cell.type:
ElementData.Type.LIQUID, ElementData.Type.POWDER:
# Try down, then down-left, then down-right
var targets = [pos + Vector2i.DOWN,
pos + Vector2i(- 1, 1),
pos + Vector2i(1, 1)]
for target in targets:
var neighbor = grid.get(target)
if neighbor and cell.should_swap_with(neighbor):
swap_cells(pos, target)
mark_dirty(target)
return
ElementData.Type.GAS:
# Gases rise (inverse of liquids)
var targets = [pos + Vector2i.UP,
pos + Vector2i(-1, -1),
pos + Vector2i(1, -1)]
# Same swap logic...
# EDGE CASE: What if multiple godot-particles want to move into same cell?
# SOLUTION: Only mark target dirty, don't double-swap. Next frame resolves conflicts.
```
### 3. Tool System (Strategy Pattern)
Decouple input from world modification.
```gdscript
# tool_base.gd
class_name Tool extends Resource
func use(world_pos: Vector2, world: WorldGrid) -> void: pass
# tool_brush.gd
extends Tool
@export var element: ElementData
@export var radius: int = 1
func use(world_pos: Vector2, world: WorldGrid) -> void:
var grid_pos = Vector2i(floor(world_pos.x), floor(world_pos.y))
# Circle brush pattern
for x in range(-radius, radius + 1):
for y in range(-radius, radius + 1):
if x*x + y*y <= radius*radius: # Circle boundary
var target = grid_pos + Vector2i(x, y)
world.set_cell(target, element)
# FALLBACK: If element placement fails (e.g., occupied by indestructible block)?
# Check world.can_place(target) before set_cell(), show visual feedback.
```
### 4. Chunk-Based Rendering (3D Voxels)
Only render visible faces. Use greedy meshing to merge adjacent blocks.
```gdscript
# See scripts/voxel_chunk_manager.gd for full implementation
# EXPERT DECISION TREE:
# - Small worlds (<100k blocks): Single MeshInstance with SurfaceTool
# - Medium worlds (100k-1M blocks): Chunked MultiMesh (see script)
# - Large worlds (>1M blocks): Chunked + greedy meshing + LOD
```
## Save System for Sandbox Worlds
```gdscript
# chunk_save_data.gd
class_name ChunkSaveData extends Resource
@export var chunk_coord: Vector2i
@export var rle_data: PackedInt32Array # [type_id, count, type_id, count...]
# EXPERT TECHNIQUE: Run-Length Encoding
static func encode_chunk(grid: Dictionary, chunk_pos: Vector2i, chunk_size: int) -> ChunkSaveData:
var data = ChunkSaveData.new()
data.chunk_coord = chunk_pos
var run_type: int = -1
var run_count: int = 0
for y in range(chunk_size):
for x in range(chunk_size):
var world_pos = chunk_pos * chunk_size + Vector2i(x, y)
var cell = grid.get(world_pos)
var type_id = cell.id if cell else 0 # 0 = air
if type_id == run_type:
run_count += 1
else:
if run_count > 0:
data.rle_data.append(run_type)
data.rle_data.append(run_count)
run_type = type_id
run_count = 1
# Flush final run
if run_count > 0:
data.rle_data.append(run_type)
data.rle_data.append(run_count)
return data
# COMPRESSION RESULT: Empty chunk (16ร16 = 256 blocks of air)
# Without RLE: 256 integers = 1024 bytes
# With RLE: [0, 256] = 8 bytes (128x cRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.