Files
minecraft-aiworld/scripts/enable-beta-apis.py
SysAdmin c12a468958 fix(transfer): use transferPlayer() beta API and enable experiments in level.dat
Switch from runCommand("transfer ...") to the @minecraft/server-admin
transferPlayer() function for reliable server-to-server transfers.
Enable Beta APIs experiment (gametest flag) in all 4 world level.dat files.
Add spawn protection to prevent transfer loops on arrival.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 02:34:29 +00:00

109 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""
Enable Beta APIs experiment in a Bedrock level.dat file.
Bedrock level.dat format:
- 4 bytes: version (little-endian int32)
- 4 bytes: payload length (little-endian int32)
- rest: uncompressed little-endian NBT payload
This script patches the 'experiments' compound tag to add:
- gametest = 1 (byte)
- experiments_ever_used = 1 (byte)
- saved_with_toggled_experiments = 1 (byte)
Requires: amulet-nbt (pip install amulet-nbt)
"""
import struct
import sys
import shutil
import amulet_nbt
def patch_level_dat(path: str) -> None:
# Read the file
with open(path, "rb") as f:
header = f.read(8)
payload = f.read()
version, length = struct.unpack("<II", header)
print(f" Header: version={version}, payload_length={length}")
print(f" Actual payload size: {len(payload)}")
# Parse little-endian NBT (Bedrock format)
nbt = amulet_nbt.load(payload, little_endian=True)
root = nbt.compound
# Find experiments compound
if "experiments" not in root:
print(" ERROR: 'experiments' compound tag not found!")
sys.exit(1)
experiments = root["experiments"]
print(f" Current experiments: {dict((k, v) for k, v in experiments.items())}")
changed = False
# Set flags to 1
for key in ("experiments_ever_used", "saved_with_toggled_experiments"):
if key in experiments:
if experiments[key].py_int == 0:
experiments[key] = amulet_nbt.ByteTag(1)
changed = True
print(f" Set {key} = 1")
else:
experiments[key] = amulet_nbt.ByteTag(1)
changed = True
print(f" Added {key} = 1")
# Add gametest experiment
if "gametest" not in experiments:
experiments["gametest"] = amulet_nbt.ByteTag(1)
changed = True
print(" Added gametest = 1")
elif experiments["gametest"].py_int == 0:
experiments["gametest"] = amulet_nbt.ByteTag(1)
changed = True
print(" Set gametest = 1")
if not changed:
print(" Already patched — no changes needed.")
return
# Serialize back (uncompressed, little-endian for Bedrock)
new_payload = nbt.save_to(little_endian=True, compressed=False)
# Build new header with updated length
new_header = struct.pack("<II", version, len(new_payload))
# Backup original
backup_path = path + ".bak"
shutil.copy2(path, backup_path)
print(f" Backup saved to {backup_path}")
# Write patched file
with open(path, "wb") as f:
f.write(new_header)
f.write(new_payload)
print(f" Patched! New payload size: {len(new_payload)}")
def main():
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <level.dat> [level.dat ...]")
sys.exit(1)
for path in sys.argv[1:]:
print(f"\nPatching: {path}")
patch_level_dat(path)
print("\nDone!")
if __name__ == "__main__":
main()