#!/usr/bin/env bash # Disposable, headless smoke check for the incomplete 26.3 runtime Age backend. set -euo pipefail repo_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) smoke_dir=$(mktemp -d "${TMPDIR:-/tmp}/rivencraft-263-smoke.XXXXXX") server_dir="$smoke_dir/server" server_pid= input_fd= cleanup() { if [[ -n "$server_pid" ]] && kill -0 "$server_pid" 2>/dev/null; then if [[ -n "$input_fd" ]]; then printf 'stop\n' >&"$input_fd" || true; fi wait "$server_pid" 2>/dev/null || true fi if [[ -n "$input_fd" ]]; then exec {input_fd}>&-; fi rm -rf -- "$smoke_dir" } trap cleanup EXIT mkdir -p "$server_dir" printf 'eula=true\n' > "$server_dir/eula.txt" printf 'server-port=0\nonline-mode=false\nwhite-list=false\n' > "$server_dir/server.properties" wait_for_log() { local log_file=$1 pattern=$2 seconds=$3 local tries=$((seconds * 4)) for ((i = 0; i < tries; i++)); do if grep -Fq -- "$pattern" "$log_file" 2>/dev/null; then return 0; fi if ! kill -0 "$server_pid" 2>/dev/null; then printf 'Server exited before: %s\n' "$pattern" >&2 tail -80 "$log_file" >&2 return 1 fi sleep 0.25 done printf 'Timed out waiting for: %s\n' "$pattern" >&2 tail -80 "$log_file" >&2 return 1 } start_server() { local phase=$1 log_file="$smoke_dir/$phase.log" fifo="$smoke_dir/$phase.stdin" mkfifo "$fifo" exec {input_fd}<>"$fifo" "$repo_dir/gradlew" -p "$repo_dir/ports/mc263" runServer \ -PserverRunDir="$server_dir" --no-daemon < "$fifo" > "$log_file" 2>&1 & server_pid=$! wait_for_log "$log_file" 'Done (' 120 } stop_server() { printf 'stop\n' >&"$input_fd" wait "$server_pid" server_pid= exec {input_fd}>&- rm -- "$fifo" } send_and_wait() { local command=$1 result=$2 printf '%s\n' "$command" >&"$input_fd" wait_for_log "$log_file" "$result" 60 } start_server first send_and_wait 'rivencraft_port compat' 'Registered biomes by namespace:' send_and_wait 'rivencraft_port age create smoke_alpha 123456789' 'Created rivencraft:age/smoke_alpha with seed 123456789' send_and_wait 'rivencraft_port age create smoke_beta 987654321' 'Created rivencraft:age/smoke_beta with seed 987654321' send_and_wait 'rivencraft_port age create smoke_flat 24680 flat' 'Created rivencraft:age/smoke_flat with seed 24680 terrain=FLAT' send_and_wait 'rivencraft_port age create smoke_void 13579 void' 'Created rivencraft:age/smoke_void with seed 13579 terrain=VOID' send_and_wait 'rivencraft_port age create smoke_cave 112233 cave' 'Created rivencraft:age/smoke_cave with seed 112233 terrain=CAVE' send_and_wait 'rivencraft_port age create_multi smoke_flat_multi 24681 flat' 'Created rivencraft:age/smoke_flat_multi with seed 24681 terrain=FLAT' send_and_wait 'rivencraft_port age create_multi smoke_void_multi 13580 void' 'Created rivencraft:age/smoke_void_multi with seed 13580 terrain=VOID' send_and_wait 'rivencraft_port age create_multi smoke_cave_multi 112234 cave' 'Created rivencraft:age/smoke_cave_multi with seed 112234 terrain=CAVE' # The index must reach disk while the server is still running. A graceful # shutdown would hide the interrupted-save regression this checks. index_file="$server_dir/world/dimensions/minecraft/overworld/data/rivencraft/runtime_ages.dat" [[ -s "$index_file" ]] || { printf 'Age index was not persisted before shutdown: %s\n' "$index_file" >&2 exit 1 } gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_alpha' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_beta' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_flat' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_void' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_cave' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_flat_multi' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_void_multi' gzip -dc "$index_file" | strings | grep -Fq 'rivencraft:age/smoke_cave_multi' send_and_wait 'rivencraft_port age sample smoke_alpha' 'rivencraft:age/smoke_alpha seed=123456789 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_beta' 'rivencraft:age/smoke_beta seed=987654321 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_flat' 'rivencraft:age/smoke_flat seed=24680 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_void' 'rivencraft:age/smoke_void seed=13579 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_cave' 'rivencraft:age/smoke_cave seed=112233 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_flat_multi' 'rivencraft:age/smoke_flat_multi seed=24681 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_void_multi' 'rivencraft:age/smoke_void_multi seed=13580 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_cave_multi' 'rivencraft:age/smoke_cave_multi seed=112234 chunkOffset=0 terrain=' send_and_wait 'execute in rivencraft:age/smoke_flat run forceload add 0 0' 'Marked chunk [0, 0] in rivencraft:age/smoke_flat to be force loaded' send_and_wait 'execute in rivencraft:age/smoke_void run forceload add 0 0' 'Marked chunk [0, 0] in rivencraft:age/smoke_void to be force loaded' send_and_wait 'execute in rivencraft:age/smoke_flat_multi run forceload add 0 0' 'Marked chunk [0, 0] in rivencraft:age/smoke_flat_multi to be force loaded' send_and_wait 'execute in rivencraft:age/smoke_void_multi run forceload add 0 0' 'Marked chunk [0, 0] in rivencraft:age/smoke_void_multi to be force loaded' send_and_wait 'execute in rivencraft:age/smoke_cave run forceload add 0 0' 'Marked chunk [0, 0] in rivencraft:age/smoke_cave to be force loaded' send_and_wait 'execute in rivencraft:age/smoke_cave_multi run forceload add 0 0' 'Marked chunk [0, 0] in rivencraft:age/smoke_cave_multi to be force loaded' send_and_wait 'execute in rivencraft:age/smoke_flat if block 0 0 0 minecraft:bedrock run say Flat bedrock starts at Y0' 'Flat bedrock starts at Y0' send_and_wait 'execute in rivencraft:age/smoke_flat if block 0 3 0 minecraft:grass_block run say Flat surface is Y3' 'Flat surface is Y3' send_and_wait 'execute in rivencraft:age/smoke_void if block 0 0 0 minecraft:air run say Void remains empty' 'Void remains empty' send_and_wait 'execute in rivencraft:age/smoke_flat_multi if block 0 0 0 minecraft:bedrock run say Multi Flat bedrock starts at Y0' 'Multi Flat bedrock starts at Y0' send_and_wait 'execute in rivencraft:age/smoke_void_multi if block 0 0 0 minecraft:air run say Multi Void remains empty' 'Multi Void remains empty' # Check region interiors after loading the sampled chunks. send_and_wait 'rivencraft_port age biome smoke_flat_multi 128 128' 'rivencraft:age/smoke_flat_multi biome at 128,128=minecraft:plains' send_and_wait 'rivencraft_port age biome smoke_flat_multi 384 128' 'rivencraft:age/smoke_flat_multi biome at 384,128=minecraft:forest' send_and_wait 'rivencraft_port age biome smoke_void_multi 384 128' 'rivencraft:age/smoke_void_multi biome at 384,128=minecraft:forest' send_and_wait 'rivencraft_port age biome smoke_cave_multi 128 128' 'rivencraft:age/smoke_cave_multi biome at 128,128=minecraft:lush_caves' send_and_wait 'rivencraft_port age biome smoke_cave_multi 384 128' 'rivencraft:age/smoke_cave_multi biome at 384,128=minecraft:dripstone_caves' alpha_before=$(grep -F 'rivencraft:age/smoke_alpha seed=123456789 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') beta_before=$(grep -F 'rivencraft:age/smoke_beta seed=987654321 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') flat_before=$(grep -F 'rivencraft:age/smoke_flat seed=24680 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') void_before=$(grep -F 'rivencraft:age/smoke_void seed=13579 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') if [[ "$alpha_before" == "$beta_before" ]]; then printf 'Different Age seeds produced the same terrain probe: %s\n' "$alpha_before" >&2 exit 1 fi if [[ "$flat_before" == "$void_before" ]]; then printf 'Flat and Void Ages produced the same height probe: %s\n' "$flat_before" >&2 exit 1 fi stop_server start_server restart send_and_wait 'rivencraft_port age list' 'smoke_alpha' send_and_wait 'rivencraft_port age sample smoke_alpha' 'rivencraft:age/smoke_alpha seed=123456789 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_beta' 'rivencraft:age/smoke_beta seed=987654321 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_flat' 'rivencraft:age/smoke_flat seed=24680 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_void' 'rivencraft:age/smoke_void seed=13579 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_cave' 'rivencraft:age/smoke_cave seed=112233 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_flat_multi' 'rivencraft:age/smoke_flat_multi seed=24681 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_void_multi' 'rivencraft:age/smoke_void_multi seed=13580 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age sample smoke_cave_multi' 'rivencraft:age/smoke_cave_multi seed=112234 chunkOffset=0 terrain=' send_and_wait 'rivencraft_port age biome smoke_flat_multi 384 128' 'rivencraft:age/smoke_flat_multi biome at 384,128=minecraft:forest' send_and_wait 'rivencraft_port age biome smoke_void_multi 384 128' 'rivencraft:age/smoke_void_multi biome at 384,128=minecraft:forest' send_and_wait 'rivencraft_port age biome smoke_cave_multi 384 128' 'rivencraft:age/smoke_cave_multi biome at 384,128=minecraft:dripstone_caves' alpha_after=$(grep -F 'rivencraft:age/smoke_alpha seed=123456789 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') beta_after=$(grep -F 'rivencraft:age/smoke_beta seed=987654321 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') flat_after=$(grep -F 'rivencraft:age/smoke_flat seed=24680 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') void_after=$(grep -F 'rivencraft:age/smoke_void seed=13579 chunkOffset=0 terrain=' "$log_file" | tail -1 | sed 's/.*terrain=//') [[ "$alpha_before" == "$alpha_after" && "$beta_before" == "$beta_after" ]] || { printf 'Age terrain changed across restart: %s/%s -> %s/%s\n' \ "$alpha_before" "$beta_before" "$alpha_after" "$beta_after" >&2 exit 1 } [[ "$flat_before" == "$flat_after" && "$void_before" == "$void_after" ]] || { printf 'Flat/Void terrain changed across restart: %s/%s -> %s/%s\n' \ "$flat_before" "$void_before" "$flat_after" "$void_after" >&2 exit 1 } stop_server printf '26.3 dedicated-server smoke passed: Standard, Flat, Void and Cave Ages persisted across restart.\n'