extends SceneTree ## 0.6.0 (docs/WORLDLETS_DESIGN.md ยง5): the Cove's wreck and the treasure map. ## The wreck is on the Cove's beach (and not in the Valley); driftwood and ## salt wash up on the sand; the captain's sea chest gives each player a ## treasure map, nails and salt, once; the map's X is that player's own (and ## somewhere else for the next player); reading the map tells you, and the X ## is on your N map while you carry it; who's had their share is saved. ## Run: godot --headless --path . --script res://tests/test_wreck.gd var _fails := 0 var _finished := false var S: Node var A: Node var _toasts: Array[String] = [] func check(cond: bool, what: String) -> void: print((" ok " if cond else " FAIL ") + what) if not cond: _fails += 1 func _initialize() -> void: _run.call_deferred() func _run() -> void: S = root.get_node("Saves") A = root.get_node("Actions") A.notify.connect(func(t): _toasts.append(t)) S.root_dir = "user://test_wreck_worlds" for w in S.list_worlds(): S.delete_world(w.id) await _body() check(_finished, "test ran to the end (no script errors)") for w in S.list_worlds(): S.delete_world(w.id) DirAccess.remove_absolute(S.root_dir) print("RESULT: %s (%d failures)" % ["PASS" if _fails == 0 else "FAIL", _fails]) quit(1 if _fails > 0 else 0) func _load() -> Node3D: var w: Node3D = load("res://scenes/world.tscn").instantiate() root.add_child(w) for _i in range(8): await physics_frame w.creatures.enabled = false w.player.set_physics_process(false) w.player.survival.set_process(false) return w func _drop(w: Node3D) -> void: w.queue_free() for _i in range(3): await process_frame func _body() -> void: print("the Valley") S.current_id = S.create_world("Valley", 1337) var w: Node3D = await _load() check(w.wreck == null, "no wreck in the Valley") check(not w.props.pickups.values().any(func(p): return p.item_id == "driftwood"), "and no driftwood") await _drop(w) print("the wreck") S.current_id = S.create_world("Cove", 1337, {"worldlet": "cove"}) w = await _load() var t: Node3D = w.terrain var wk: Node3D = w.wreck check(wk != null and t.beach_weight(wk.global_position.x, wk.global_position.z) > 0.5, "a wreck on the Cove's beach") if wk == null: return check(wk.global_position.distance_to(w.sea_cave.global_position) > 60.0, "at the far end of the bay from the sea cave (%.0f m)" % wk.global_position.distance_to(w.sea_cave.global_position)) check(w.water_at(wk.front.x, wk.front.z).is_empty() or float(w.water_at(wk.front.x, wk.front.z).depth) < 0.6, "you can stand beside it to reach the chest") var drift: Array = w.props.pickups.values().filter(func(p): return p.item_id == "driftwood") check(drift.size() >= 20 and drift.all(func(p): return t.beach_weight(p.global_position.x, p.global_position.z) > 0.5), "driftwood along the sand (%d)" % drift.size()) check(w.props.pickups.values().any(func(p): return p.item_id == "salt"), "and salt crusts by the waterline") print("the captain's sea chest") var p: Node3D = w.player var me: String = w.my_id() p.global_position = wk.front check(wk.chest.interact_prompt(p).begins_with("[E] Open"), "[E] Open the captain's sea chest") wk.chest.interact(p) check(p.inventory.count("treasure_map") == 1 and p.inventory.count("nails") >= 4 and p.inventory.count("salt") >= 2, "a torn treasure map, nails and salt") check(_toasts.any(func(s): return String(s).begins_with("In the captain's sea chest")), "(and it says so)") _toasts.clear() wk.chest.interact(p) check(p.inventory.count("treasure_map") == 1 and _toasts.has("The sea chest's empty: you've had what was in it"), "once: the second time it's empty") check(wk.open_for(p, "someone-else"), "someone else gets their own share") p.inventory.remove("treasure_map", 1) # (it went in this bag: theirs, not ours) print("the map") var x: Vector3 = w.treasure_spot(me) check(x != Vector3.INF and t.inside_boundary(x.x, x.z, 10.0) and x.y > t.water_level + 1.5, "your X: dry ground in the hills (%s)" % x) var others := 0 for i in range(8): if w.treasure_spot("player-%d" % i).distance_to(x) > 20.0: others += 1 check(others >= 5, "and other players' X are mostly somewhere else (%d of 8)" % others) check(w.treasure_spot(me) == x, "(the same every time for you)") check(w.map_marks().any(func(m): return m.kind == "treasure" and m.pos == x), "on your map while you carry it, even where you haven't been") _toasts.clear() w.read_map(p) check(_toasts.any(func(s): return String(s).begins_with("X marks the spot")), "reading it: X marks the spot") p.inventory.remove("treasure_map", 1) check(not w.map_marks().any(func(m): return m.kind == "treasure"), "(no map, no X)") p.inventory.add("treasure_map", 1) w.explore(wk.global_position) check(w.map_marks().any(func(m): return m.kind == "wreck"), "the wreck's on the map once you've seen it") print("saved") w.save_now() await _drop(w) w = await _load() check(w.wreck.had(me) and w.wreck.had("someone-else") and not w.wreck.had("a-stranger"), "who's had their share is kept") await _drop(w) _finished = true