Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 62 additions & 55 deletions .claude/commands/new-block.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ $ARGUMENTS

## Instructions

You are scaffolding a new block in a Minecraft plugin (Paper/Kotlin) that uses the Nexo resource pack system and a custom block framework. Follow the existing patterns exactly.
You are scaffolding a new block in a Minecraft plugin (Paper/Kotlin) that uses the CraftEngine resource pack system and a custom block framework. Follow the existing patterns exactly.

### Step 1: Gather Info

Expand Down Expand Up @@ -76,67 +76,74 @@ class {ClassName}(location: Location) : {BaseClass}(location, maxStorage = {N})

**DIRECTIONAL_OPPOSITE block** (like SmallDrill): Same directional pattern but placement type is `DIRECTIONAL_OPPOSITE`.

### Step 3: Add Block Definitions to atlas_blocks.yml
### Step 3: Add CraftEngine Block Configuration

Append to `src/main/resources/nexo/items/atlas_blocks.yml`.
Create `src/main/resources/atlas/configuration/{block_id}.yml`.

Find the next available `custom_variation` number. Power blocks use 100+ range, fluid blocks use 1-43 range. Check the file for the highest used number in the relevant range and increment.
Follow the CraftEngine configuration format. Each variant gets its own `items` section (use `items#1`, `items#2`, etc. for additional variants). The base variant uses `loot: template: default:loot_table/self`, while other variants use explicit loot pools that drop the base item.

Reference existing configuration files (e.g., `small_solar_panel.yml`, `lava_generator.yml`) for the exact format. Here's the general structure:

Each variant needs its own YAML entry:
```yaml
{block_id}:
itemname: "<gradient:{color1}:{color2}>{Display Name}"
material: paper
Pack:
generate_model: true
parent_model: block/cube # or block/cube_all for same texture on all faces
textures:
north: atlas:block/{texture_name}
south: atlas:block/{texture_name}
east: atlas:block/{texture_name}
west: atlas:block/{texture_name}
up: atlas:block/{texture_top}
down: atlas:block/{texture_bottom}
Mechanics:
custom_block:
type: NOTEBLOCK
custom_variation: {next_available_number}
hardness: 5
block_sounds:
break_sound: block.metal.break
place_sound: block.metal.place
hit_sound: block.metal.hit
step_sound: block.metal.step
fall_sound: block.metal.fall
drop:
silktouch: false
loots:
- nexo_item: {base_block_id} # ALWAYS drops the base ID, not the variant
probability: 1.0
items:
atlas:{block_id}:
material: paper
data:
item-name: "<!i><gradient:{color1}:{color2}>{Display Name}"
model: minecraft:block/custom/{block_id}
behavior:
type: block_item
block:
loot:
template: default:loot_table/self
settings:
hardness: 4.0
resistance: 4.0
is-suffocating: true
is-redstone-conductor: false
push-reaction: push_only
tags: ["minecraft:mineable/pickaxe"]
sounds:
break: minecraft:block.metal.break
step: minecraft:block.metal.step
place: minecraft:block.metal.place
hit: minecraft:block.metal.hit
fall: minecraft:block.metal.fall
state:
auto-state: solid
model:
path: minecraft:block/custom/{block_id}
generation:
parent: minecraft:block/cube_bottom_top # or block/cube, block/cube_all
textures:
top: minecraft:block/custom/{block_id}_top
bottom: minecraft:block/custom/{block_id}_bottom
side: minecraft:block/custom/{block_id}_side
```

Notes:
- All variant entries (active, directional, etc.) must each have a unique `custom_variation` number
- The `drop` always references the base block ID so variants drop the right item
- Use `block/cube_all` with `all:` texture if all 6 faces are the same
- Use `block/cube` with individual face textures if faces differ
- Use `block/cube_bottom_top` with `top:`, `bottom:`, `side:` if top/bottom differ from sides
For additional variant entries (active states, directional, etc.), add `items#1`, `items#2`, etc. sections with explicit loot that drops the base item:
```yaml
items#1:
atlas:{block_id}_{variant}:
# ... same structure but with:
# loot pools that drop atlas:{block_id} (the base item)
```

### Step 4: Add Recipe

Append to `src/main/resources/nexo/recipes/shapeless/atlas_recipes.yml`:
Add the recipe in the same configuration file. Append a `recipes:` section:
```yaml
{block_id}_recipe:
result:
nexo_item: {block_id}
amount: 1
ingredients:
A:
amount: {n}
minecraft_type: {MATERIAL}
B:
amount: {n}
minecraft_type: {MATERIAL}
recipes:
atlas:{block_id}:
type: shapeless
category: misc
unlock-on-ingredient-obtained: true
ingredients:
- minecraft:{material}
- minecraft:{material}
result:
id: atlas:{block_id}
count: 1
```

### Step 5: Register in Atlas.kt
Expand Down Expand Up @@ -178,7 +185,7 @@ For **fluid blocks**, edit `src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockD

### Step 8: Generate Placeholder Textures

Create 128x128 PNG placeholder textures at `src/main/resources/nexo/pack/assets/atlas/textures/block/`.
Create 128x128 PNG placeholder textures at `src/main/resources/atlas/resourcepack/assets/minecraft/textures/block/custom/`.

Use Python with Pillow to generate dark industrial-style textures matching the project's art style:
- Base color: dark gray/charcoal (~38,38,44 RGB)
Expand All @@ -194,8 +201,8 @@ Name textures following the convention: `{block_id}_{face}.png`, `{block_id}_{fa
Before finishing, verify:
- [ ] Block class created with correct descriptor
- [ ] All variant IDs listed in `allRegistrableIds`
- [ ] YAML entries added for every variant with unique `custom_variation` numbers
- [ ] Recipe added
- [ ] CraftEngine configuration YAML created with all variants
- [ ] Recipe added in the configuration file
- [ ] Descriptor registered in Atlas.kt
- [ ] Dialog cases added
- [ ] TestHelper updated with new descriptor
Expand Down
23 changes: 11 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>nexomc</id>
<name>NexoMC Repository</name>
<url>https://repo.nexomc.com/releases</url>
<id>momirealms-repo</id>
<url>https://repo.momirealms.net/releases/</url>
</repository>
</repositories>

Expand Down Expand Up @@ -184,16 +183,16 @@
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.nexomc</groupId>
<artifactId>nexo</artifactId>
<version>1.20.1</version>
<groupId>net.momirealms</groupId>
<artifactId>craft-engine-core</artifactId>
<version>0.0.67</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.momirealms</groupId>
<artifactId>craft-engine-bukkit</artifactId>
<version>0.0.67</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
86 changes: 37 additions & 49 deletions run-server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ SERVER_DIR="run"
MINECRAFT_VERSION="1.21.11"

# Create server directory if it doesn't exist
mkdir -p "$SERVER_DIR/plugins/Atlas"
mkdir -p "$SERVER_DIR/plugins/Nexo/items"
mkdir -p "$SERVER_DIR/plugins/Nexo/recipes/shapeless"
mkdir -p "$SERVER_DIR/plugins/Nexo/pack/assets/atlas/textures/block"
mkdir -p "$SERVER_DIR/plugins"
mkdir -p "$SERVER_DIR/plugins/CraftEngine/resources"

# Build the plugin
echo "Building plugin..."
Expand All @@ -22,59 +20,61 @@ fi
# Copy the plugin to the server
cp target/Atlas-*.jar "$SERVER_DIR/plugins/"

# Check for Nexo plugin (accept any nexo*.jar or Nexo*.jar file)
NEXO_JAR=$(find "$SERVER_DIR/plugins" -maxdepth 1 \( -name "nexo*.jar" -o -name "Nexo*.jar" \) 2>/dev/null | head -1)

# Validate the JAR has plugin.yml (not just the API artifact)
if [ -n "$NEXO_JAR" ]; then
if ! unzip -l "$NEXO_JAR" 2>/dev/null | grep -q "plugin.yml"; then
echo "Found invalid Nexo JAR (API artifact, not plugin). Removing..."
rm -f "$NEXO_JAR"
rm -rf "$SERVER_DIR/plugins/.paper-remapped/nexo-"*
rm -rf "$SERVER_DIR/plugins/.paper-remapped/Nexo-"*
NEXO_JAR=""
# Copy the plugin to the server
cp target/Atlas-Experimental-*.jar "$SERVER_DIR/plugins/"

# Copy CraftEngine pack (configuration + textures)
echo "Setting up CraftEngine pack..."
rm -rf "$SERVER_DIR/plugins/CraftEngine/resources/atlas"
cp -r src/main/resources/atlas "$SERVER_DIR/plugins/CraftEngine/resources/atlas"

# Check for CraftEngine plugin
CE_JAR=$(find "$SERVER_DIR/plugins" -maxdepth 1 \( -name "craft-engine*.jar" -o -name "CraftEngine*.jar" \) 2>/dev/null | head -1)

if [ -n "$CE_JAR" ]; then
if ! unzip -l "$CE_JAR" 2>/dev/null | grep -q "plugin.yml\|paper-plugin.yml"; then
echo "Found invalid CraftEngine JAR (API artifact, not plugin). Removing..."
rm -f "$CE_JAR"
rm -rf "$SERVER_DIR/plugins/.paper-remapped/craft-engine-"*
rm -rf "$SERVER_DIR/plugins/.paper-remapped/CraftEngine-"*
CE_JAR=""
fi
fi

if [ -z "$NEXO_JAR" ]; then
# Clean up any corrupted files
rm -rf "$SERVER_DIR/plugins/.paper-remapped/nexo-"*
rm -rf "$SERVER_DIR/plugins/.paper-remapped/Nexo-"*
if [ -z "$CE_JAR" ]; then
rm -rf "$SERVER_DIR/plugins/.paper-remapped/craft-engine-"*
rm -rf "$SERVER_DIR/plugins/.paper-remapped/CraftEngine-"*

echo ""
echo "=============================================="
echo " Nexo plugin not found!"
echo " CraftEngine plugin not found!"
echo "=============================================="
echo ""
echo " Download from Polymart:"
echo " https://polymart.org/resource/nexo.6901"
echo " https://polymart.org/product/7624/craftengine"
echo ""
echo " Or from BuiltByBit:"
echo " https://builtbybit.com/resources/nexo.36138/"
echo " https://builtbybit.com/resources/craftengine.82674/"
echo ""
echo " Or from Modrinth:"
echo " https://modrinth.com/plugin/craftengine"
echo ""
echo " Then place the JAR in:"
echo " $(pwd)/$SERVER_DIR/plugins/"
echo ""
echo " NOTE: The Maven repository only has the API."
echo " You need the full plugin from Polymart/BuiltByBit."
echo " You need the full plugin JAR."
echo "=============================================="
echo ""
exit 1
fi

echo "Found Nexo: $NEXO_JAR"
echo "Found CraftEngine: $CE_JAR"

# Pre-copy Atlas Nexo configurations (so they're available on first startup)
echo "Setting up Atlas Nexo configurations..."
cp "src/main/resources/nexo/items/atlas_blocks.yml" "$SERVER_DIR/plugins/Nexo/items/"
cp "src/main/resources/nexo/recipes/shapeless/atlas_recipes.yml" "$SERVER_DIR/plugins/Nexo/recipes/shapeless/"
cp src/main/resources/nexo/pack/assets/atlas/textures/block/small_solar_panel_*.png "$SERVER_DIR/plugins/Nexo/pack/assets/atlas/textures/block/"
cp src/main/resources/nexo/pack/assets/atlas/textures/block/power_cable_*.png "$SERVER_DIR/plugins/Nexo/pack/assets/atlas/textures/block/"

# Create/update the Atlas plugin config (resource pack disabled - Nexo handles it)
# Create/update the Atlas plugin config (resource pack disabled - CraftEngine handles it)
cat > "$SERVER_DIR/plugins/Atlas/config.yml" << EOF
# Atlas Plugin Configuration (auto-generated for testing)
# Resource pack is disabled because Nexo handles resource pack generation and hosting
# Resource pack is disabled because CraftEngine handles resource pack generation and hosting

logging: false

Expand All @@ -86,7 +86,7 @@ resource-pack:
prompt: ""
EOF

echo "Atlas config created (resource pack disabled - Nexo handles it)"
echo "Atlas config created (resource pack disabled - CraftEngine handles it)"

# Download Paper if not present or update to latest build
cd "$SERVER_DIR"
Expand All @@ -111,24 +111,23 @@ fi
# Accept EULA
echo "eula=true" > eula.txt

# Configure Paper for Nexo (disable noteblock/tripwire/chorus updates for performance)
# Configure Paper for CraftEngine (disable noteblock/tripwire/chorus updates for performance)
mkdir -p "config"
if [ ! -f "config/paper-global.yml" ]; then
cat > "config/paper-global.yml" << EOF
# Paper Global Configuration
# Optimized for Nexo custom blocks

block-updates:
disable-noteblock-updates: true
disable-tripwire-updates: true
disable-chorus-plant-updates: true
EOF
echo "Paper config created with Nexo optimizations"
echo "Paper config created with CraftEngine optimizations"
else
# Check if optimizations are already present, if not warn the user
if ! grep -q "disable-noteblock-updates: true" "config/paper-global.yml"; then
echo ""
echo "WARNING: Please add these settings to config/paper-global.yml for Nexo:"
echo "WARNING: Please add these settings to config/paper-global.yml for CraftEngine:"
echo " block-updates:"
echo " disable-noteblock-updates: true"
echo " disable-tripwire-updates: true"
Expand All @@ -137,17 +136,6 @@ else
fi
fi

echo ""
echo "=============================================="
echo " Atlas + Nexo Development Server"
echo "=============================================="
echo " Nexo will handle resource pack hosting"
echo " Craft Small Solar Panel:"
echo " 3x Iron Ingot + 3x Lapis + 3x Redstone"
echo " Use /nexo reload to reload configurations"
echo "=============================================="
echo ""

# Run the server
echo "Starting Paper server..."
java -Xms1G -Xmx2G -jar "$PAPER_JAR" --nogui
4 changes: 2 additions & 2 deletions scripts/generate_fluid_textures.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

OUTPUT_DIR = os.path.join(
os.path.dirname(__file__), "..",
"src", "main", "resources", "nexo", "pack",
"assets", "atlas", "textures", "block"
"src", "main", "resources", "atlas", "resourcepack",
"assets", "minecraft", "textures", "block", "custom"
)

S = 32 # texture size
Expand Down
4 changes: 2 additions & 2 deletions scripts/generate_power_cable_textures.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

OUTPUT_DIR = os.path.join(
os.path.dirname(__file__), "..",
"src", "main", "resources", "nexo", "pack",
"assets", "atlas", "textures", "block"
"src", "main", "resources", "atlas", "resourcepack",
"assets", "minecraft", "textures", "block", "custom"
)

# Colors
Expand Down
4 changes: 2 additions & 2 deletions scripts/generate_textures.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

OUTPUT_DIR = os.path.join(
os.path.dirname(__file__), "..",
"src", "main", "resources", "nexo", "pack",
"assets", "atlas", "textures", "block"
"src", "main", "resources", "atlas", "resourcepack",
"assets", "minecraft", "textures", "block", "custom"
)

# Indicator light colors (2x2 block in bottom-right corner)
Expand Down
Loading
Loading