Cobblemon Survival Pack: phases 0-2 and Phase 3 zones and hazards
Free NeoForge 1.21.1 modpack on Cobblemon 1.8.4 built with packwiz, plus the Kotlin companion mod (cobblesurvival) and its built-in data pack. - Phase 0: packwiz pack with Modrinth/CurseForge cross-links, build and export tooling, Prism instance sync, test server with smoke checks. - Phase 1: Poke Ball shaped island (WorldGen Editor preset, seed isle-26), Adrian's biome list, no natural ore, structures without ore or vanilla mobs, no Nether portals, world template builder and world report. - Phase 2: permadeath (CobbleHardcoreMon plus the companion mod's gap fixes), Revival Charm, expensive Healing Machine, Lootr refreshing loot, in-game self-tests on Minecraft's GameTest framework. - Phase 3 so far: 14 zones with their own spawn pools and level bands (tools/zone_layout.py, tools/zone_spawns.py, "zone" spawn condition), Cold Sweat heat and cold as gates with boss-drop insulation recipes, spawn survey and hazard self-tests in tools/quick_check.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
398301f0be
232 files changed
+72665
No files matched your search
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Server smoke test: boot a dedicated NeoForge server with the pack, check it
|
||||
over RCON, scan the log, stop.
|
||||
|
||||
Steps
|
||||
1. Install the NeoForge server named in pack/pack.toml (cached in build/.cache).
|
||||
2. Install the server-side mods from build/stage/full with packwiz-installer
|
||||
and check their dependency ranges (tools/check_deps.py).
|
||||
3. Use the world template from build/world-template when it exists
|
||||
(tools/make_world.py), otherwise generate a fresh island world.
|
||||
4. Start the server with RCON on a free local port and wait for "Done (".
|
||||
5. Run every check in tools/smoke_checks.json over RCON (a check may have
|
||||
"setup" and "cleanup" command lists around its command).
|
||||
6. Stop the server, then fail on log lines that match no entry in
|
||||
tools/smoke_allowlist.txt.
|
||||
|
||||
Running a dedicated server needs eula=true in eula.txt. The script only writes
|
||||
it when called with --accept-eula, which states that you accept the Minecraft
|
||||
EULA (https://aka.ms/MinecraftEULA) for this test server.
|
||||
|
||||
--load-only needs no EULA. NeoForge discovers every mod jar and prints its mod
|
||||
list before the server checks eula.txt, then stops at the EULA notice; mods
|
||||
are only constructed after that check. So it proves the loader reads every
|
||||
jar (with tools/check_deps.py covering dependency ranges), not that the mods
|
||||
start; construction, world, datapack and RCON checks need the full run.
|
||||
|
||||
Usage: tools/smoke_test.py --accept-eula [--keep] [--timeout SECONDS]
|
||||
tools/smoke_test.py --load-only
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from mcserver import BUILD, ROOT, SERVER, Server, eula_accepted, prepare, scan_log # noqa: E402
|
||||
|
||||
TEMPLATE = BUILD / "world-template"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument("--accept-eula", action="store_true", help="write eula=true for the test server")
|
||||
parser.add_argument("--load-only", action="store_true", help="stop at the EULA check (no EULA needed)")
|
||||
parser.add_argument("--keep", action="store_true", help="keep the server world between runs")
|
||||
parser.add_argument("--timeout", type=int, default=900, help="seconds to wait for startup")
|
||||
args = parser.parse_args()
|
||||
if not args.accept_eula and not args.load_only:
|
||||
sys.exit("Refusing to start: pass --accept-eula to accept the Minecraft EULA for this test server, "
|
||||
"or --load-only to stop at the EULA check.")
|
||||
|
||||
args_file = prepare()
|
||||
world = SERVER / "world"
|
||||
if not args.keep:
|
||||
shutil.rmtree(world, ignore_errors=True)
|
||||
if (TEMPLATE / "level.dat").exists():
|
||||
shutil.copytree(TEMPLATE, world)
|
||||
print(f"using world template {TEMPLATE.relative_to(ROOT)}")
|
||||
if args.load_only:
|
||||
if eula_accepted():
|
||||
sys.exit("eula.txt already accepts the EULA here; run the full test with --accept-eula instead.")
|
||||
else:
|
||||
(SERVER / "eula.txt").write_text("eula=true\n")
|
||||
recipe = json.loads((ROOT / "world/world.json").read_text())
|
||||
|
||||
failures = []
|
||||
with Server(args_file, {"level-type": recipe["level_type"], "level-seed": recipe["seed"]},
|
||||
stdout_name="smoke-stdout.log") as server:
|
||||
try:
|
||||
if args.load_only:
|
||||
server.proc.wait(timeout=args.timeout)
|
||||
text = server.log.read_text(errors="replace") if server.log.exists() else ""
|
||||
for pattern, what in ((r"Cobblemon Survival Pack Companion \S+ \(cobblesurvival\)",
|
||||
"companion mod in the mod list"),
|
||||
(r"You need to agree to the EULA", "stop at the EULA check")):
|
||||
if not re.search(pattern, text):
|
||||
failures.append(f"missing {what} in the log")
|
||||
print(f"mod discovery finished in {time.time() - server.started:.0f}s")
|
||||
else:
|
||||
print(f"server started in {server.wait_ready(args.timeout):.0f}s")
|
||||
failures += server.run_checks()
|
||||
server.stop()
|
||||
except Exception as e: # report; the context manager still kills the process
|
||||
failures.append(f"{type(e).__name__}: {e}")
|
||||
|
||||
if server.log.exists():
|
||||
failures += [f"log: {line}" for line in scan_log(server.log)]
|
||||
if failures:
|
||||
print("\nSMOKE TEST FAILED")
|
||||
print("\n".join(f" - {f}" for f in failures))
|
||||
print(f" log: {server.log}")
|
||||
sys.exit(1)
|
||||
print("\nLOAD CHECK PASSED (mod discovery only; the full smoke test still needs --accept-eula)"
|
||||
if args.load_only else "\nSMOKE TEST PASSED")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user