1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

Replace PJS generator mod with PixLyzer (#38)

* pixlizer extractor

* start working on shape extraction
This commit is contained in:
mat 2022-11-07 21:06:15 -06:00 committed by GitHub
parent 7101cf85b7
commit e3e4ab98bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 285 additions and 52 deletions

View file

@ -254,6 +254,24 @@ make_block_states! {
},
"short" => bool,
"unstable" => bool,
"books_stored" => ChiseledBookshelfBooksStored {
_0,
_1,
_2,
_3,
_4,
_5,
_6,
},
"last_interaction_book_slot" => ChiseledBookshelfLastInteractionBookSlot {
_0,
_1,
_2,
_3,
_4,
_5,
_6,
},
"age" => FireAge {
_0,
_1,
@ -387,6 +405,7 @@ make_block_states! {
NorthWest,
NorthEast,
},
"attached" => bool,
"face" => Face {
Floor,
Wall,
@ -505,7 +524,6 @@ make_block_states! {
_1,
_2,
},
"attached" => bool,
"disarmed" => bool,
"conditional" => bool,
"east" => EastWall {
@ -1074,6 +1092,8 @@ make_block_states! {
acacia_planks => BlockBehavior::default(), {},
dark_oak_planks => BlockBehavior::default(), {},
mangrove_planks => BlockBehavior::default(), {},
bamboo_planks => BlockBehavior::default(), {},
bamboo_mosaic => BlockBehavior::default(), {},
oak_sapling => BlockBehavior::default(), {
stage: OakSaplingStage::_0,
},
@ -1421,6 +1441,11 @@ make_block_states! {
unstable: false,
},
bookshelf => BlockBehavior::default(), {},
chiseled_bookshelf => BlockBehavior::default(), {
books_stored: ChiseledBookshelfBooksStored::_0,
facing: FacingCardinal::North,
last_interaction_book_slot: ChiseledBookshelfLastInteractionBookSlot::_0,
},
mossy_cobblestone => BlockBehavior::default(), {},
obsidian => BlockBehavior::default(), {},
torch => BlockBehavior::default(), {},
@ -1497,6 +1522,10 @@ make_block_states! {
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
bamboo_sign => BlockBehavior::default(), {
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
oak_door => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: Half::Lower,
@ -1546,6 +1575,100 @@ make_block_states! {
facing: FacingCardinal::North,
waterlogged: false,
},
bamboo_wall_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
oak_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
spruce_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
birch_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
acacia_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
jungle_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
dark_oak_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
crimson_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
warped_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
mangrove_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
bamboo_hanging_sign => BlockBehavior::default(), {
attached: false,
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
waterlogged: false,
},
oak_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
spruce_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
birch_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
acacia_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
jungle_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
dark_oak_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
mangrove_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
crimson_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
warped_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
bamboo_wall_hanging_sign => BlockBehavior::default(), {
facing: FacingCardinal::North,
waterlogged: false,
},
lever => BlockBehavior::default(), {
face: Face::Wall,
facing: FacingCardinal::North,
@ -1582,6 +1705,9 @@ make_block_states! {
mangrove_pressure_plate => BlockBehavior::default(), {
powered: false,
},
bamboo_pressure_plate => BlockBehavior::default(), {
powered: false,
},
redstone_ore => BlockBehavior::default(), {
lit: false,
},
@ -1720,6 +1846,13 @@ make_block_states! {
powered: false,
waterlogged: false,
},
bamboo_trapdoor => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: TopBottom::Bottom,
open: false,
powered: false,
waterlogged: false,
},
stone_bricks => BlockBehavior::default(), {},
mossy_stone_bricks => BlockBehavior::default(), {},
cracked_stone_bricks => BlockBehavior::default(), {},
@ -2009,6 +2142,11 @@ make_block_states! {
facing: FacingCardinal::North,
powered: false,
},
bamboo_button => BlockBehavior::default(), {
face: Face::Wall,
facing: FacingCardinal::North,
powered: false,
},
skeleton_skull => BlockBehavior::default(), {
rotation: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15::_0,
},
@ -2246,6 +2384,18 @@ make_block_states! {
shape: StairShape::Straight,
waterlogged: false,
},
bamboo_stairs => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: TopBottom::Bottom,
shape: StairShape::Straight,
waterlogged: false,
},
bamboo_mosaic_stairs => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: TopBottom::Bottom,
shape: StairShape::Straight,
waterlogged: false,
},
slime_block => BlockBehavior::default(), {},
barrier => BlockBehavior::default(), {},
light => BlockBehavior::default(), {
@ -2466,6 +2616,14 @@ make_block_states! {
kind: Type::Bottom,
waterlogged: false,
},
bamboo_slab => BlockBehavior::default(), {
kind: Type::Bottom,
waterlogged: false,
},
bamboo_mosaic_slab => BlockBehavior::default(), {
kind: Type::Bottom,
waterlogged: false,
},
stone_slab => BlockBehavior::default(), {
kind: Type::Bottom,
waterlogged: false,
@ -2562,6 +2720,12 @@ make_block_states! {
open: false,
powered: false,
},
bamboo_fence_gate => BlockBehavior::default(), {
facing: FacingCardinal::North,
in_wall: false,
open: false,
powered: false,
},
spruce_fence => BlockBehavior::default(), {
east: false,
north: false,
@ -2604,6 +2768,13 @@ make_block_states! {
waterlogged: false,
west: false,
},
bamboo_fence => BlockBehavior::default(), {
east: false,
north: false,
south: false,
waterlogged: false,
west: false,
},
spruce_door => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: Half::Lower,
@ -2646,6 +2817,13 @@ make_block_states! {
open: false,
powered: false,
},
bamboo_door => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: Half::Lower,
hinge: Hinge::Left,
open: false,
powered: false,
},
end_rod => BlockBehavior::default(), {
facing: FacingCubic::Up,
},

View file

@ -6,7 +6,7 @@ The directory name doesn't start with `azalea-` because it's not a Rust crate.
- Python 3.8+
- Java 17+
- Gradle
- Maven
## Usage
@ -33,3 +33,14 @@ If a packet is incorrect, you'll want to find it in the Minecraft source. The na
Finally, test by making a bot join a world. Specifically, you'll want to test the things that were updated in the version. Setting the RUST_LOG environment variable to `debug` or `trace` may help (trace shows the first few hundred bytes for every packet received so it's typically more useful, but it may log more than you want).
If it all works, make a pull request. If the version you updated to is a snapshot, make it a draft PR (the main branch is for release versions).
## Extracting new data
At the time of writing, the following data generators are used:
- [Vanilla data generator](https://wiki.vg/Data_Generators)
- [Burger](https://github.com/Pokechu22/Burger)
- [PixLyzer](https://gitlab.bixilon.de/bixilon/pixlyzer)
Some things can be obtained from multiple generators. You should prefer them by the order above (the vanilla generator is the most reliable).

View file

@ -9,8 +9,10 @@ import lib.utils
version_id = lib.code.version.get_version_id()
shape_datas = lib.extract.get_generator_mod_data(
version_id, 'blockCollisionShapes')
shape_datas = lib.extract.get_pixlyzer_data(
version_id, 'shapes')
pixlyzer_block_datas = lib.extract.get_pixlyzer_data(
version_id, 'blocks')
mappings = lib.download.get_mappings_for_version(version_id)
block_states_burger = lib.extract.get_block_states_burger(version_id)
@ -21,7 +23,7 @@ lib.code.blocks.generate_blocks(
block_states_burger, block_states_report, ordered_blocks, mappings)
lib.code.shapes.generate_block_shapes(
shape_datas['blocks'], shape_datas['shapes'], block_states_report, block_states_burger, mappings)
pixlyzer_block_datas, shape_datas['shapes'], shape_datas['aabbs'], block_states_report, block_states_burger, mappings)
lib.code.utils.fmt()

View file

@ -7,8 +7,8 @@ COLLISION_BLOCKS_RS_DIR = get_dir_location(
'../azalea-physics/src/collision/blocks.rs')
def generate_block_shapes(blocks: dict, shapes: dict, block_states_report, block_datas_burger, mappings: Mappings):
blocks, shapes = simplify_shapes(blocks, shapes)
def generate_block_shapes(blocks: dict, shapes: dict, aabbs: dict, block_states_report, block_datas_burger, mappings: Mappings):
blocks, shapes = simplify_shapes(blocks, shapes, aabbs)
code = generate_block_shapes_code(
blocks, shapes, block_states_report, block_datas_burger, mappings)
@ -16,30 +16,39 @@ def generate_block_shapes(blocks: dict, shapes: dict, block_states_report, block
f.write(code)
def simplify_shapes(blocks: dict, shapes: dict):
def simplify_shapes(blocks: dict, shapes: dict, aabbs: dict):
shape_to_new_id = {}
new_id_increment = 0
new_shapes = {}
old_id_to_new_id = {}
for shape_id, shape in sorted(shapes.items(), key=lambda shape: int(shape[0])):
# tuples are hashable
shape_as_tuple = tuple(map(tuple, shape))
if shape_as_tuple not in shape_to_new_id:
shape_to_new_id[shape_as_tuple] = new_id_increment
for shape_id, shape in enumerate(shapes):
# pixlyzer gives us shapes as an index or list of indexes into the
# aabbs list
# and aabbs look like { "from": number or [x, y, z], "to": (number or vec3) }
# convert them to [x1, y1, z1, x2, y2, z2]
shape = [shape] if isinstance(shape, int) else shape
shape = [aabbs[shape_aabb] for shape_aabb in shape_aabbs]
shape = tuple([(
part['from'] if isinstance(part['from'], list) else ((part['from'],)*3)
+ part['to'] if isinstance(part['to'], list) else ((part['to'],)*3)
) for part in shape])
if shape not in shape_to_new_id:
shape_to_new_id[shape] = new_id_increment
old_id_to_new_id[shape_id] = new_id_increment
new_shapes[new_id_increment] = shape
new_id_increment += 1
else:
old_id_to_new_id[shape_id] = shape_to_new_id[shape_as_tuple]
old_id_to_new_id[shape_id] = shape_to_new_id[shape]
# now map the blocks to the new shape ids
for block_id, shape_ids in blocks.items():
for block_id, shape_ids in enumerate(blocks):
if isinstance(shape_ids, int):
blocks[block_id] = old_id_to_new_id[str(shape_ids)]
blocks[block_id] = old_id_to_new_id[shape_ids]
else:
blocks[block_id] = [old_id_to_new_id[str(shape_id)]
blocks[block_id] = [old_id_to_new_id[shape_id]
for shape_id in shape_ids]
return blocks, new_shapes

View file

@ -22,12 +22,12 @@ def get_burger():
os.system('cd downloads/Burger && pip install six jawa')
def get_generator_mod():
if not os.path.exists(get_dir_location('downloads/minecraft-data-generator-server')):
print('\033[92mDownloading u9g/minecraft-data-generator-server...\033[m')
def get_pixlyzer():
if not os.path.exists(get_dir_location('downloads/pixlyzer')):
print('\033[92mDownloading bixilon/pixlyzer...\033[m')
os.system(
f'cd {get_dir_location("downloads")} && git clone https://github.com/u9g/minecraft-data-generator-server && cd minecraft-data-generator-server && git pull')
return get_dir_location('downloads/minecraft-data-generator-server')
f'cd {get_dir_location("downloads")} && git clone https://gitlab.bixilon.de/bixilon/pixlyzer.git && cd pixlyzer && git pull')
return get_dir_location('downloads/pixlyzer')
def get_version_manifest():

View file

@ -1,10 +1,11 @@
# Extracting data from the Minecraft jars
from lib.download import get_server_jar, get_burger, get_client_jar, get_generator_mod, get_yarn_data, get_fabric_api_versions, get_fabric_loader_versions
from lib.download import get_server_jar, get_burger, get_client_jar, get_pixlyzer, get_yarn_data, get_fabric_api_versions, get_fabric_loader_versions
from lib.utils import get_dir_location
from zipfile import ZipFile
import subprocess
import json
import sys
import re
import os
@ -59,44 +60,76 @@ def determine_python_command():
raise Exception(
'Couldn\'t determine python command to use to run burger with!')
def run_python_command_and_download_deps(command):
for _ in range(10):
p = subprocess.Popen(
[command],
stderr=subprocess.PIPE,
shell=True
)
stderr = b''
while True:
data = p.stderr.read()
if data == b'': break
print(data.decode(), end='', flush=True)
stderr += data
regex_match = re.search(
r'ModuleNotFoundError: No module named \'(\w+?)\'', stderr.decode())
if not regex_match:
break
missing_lib = regex_match.group(1)
print('Missing required lib:', missing_lib)
os.system(
f'{determine_python_command()} -m pip install {missing_lib}')
def get_burger_data_for_version(version_id: str):
if not os.path.exists(get_dir_location(f'downloads/burger-{version_id}.json')):
get_burger()
get_client_jar(version_id)
for _ in range(10):
r = subprocess.run(
f'cd {get_dir_location("downloads/Burger")} && {determine_python_command()} munch.py ../client-{version_id}.jar --output ../burger-{version_id}.json',
capture_output=True,
shell=True
)
regex_match = re.search(
r'ModuleNotFoundError: No module named \'(\w+?)\'', r.stderr.decode())
if not regex_match:
break
missing_lib = regex_match.group(1)
print('Missing required lib for Burger:', missing_lib)
os.system(
f'{determine_python_command()} -m pip install {missing_lib}')
run_python_command_and_download_deps(
f'cd {get_dir_location("downloads/Burger")} && {determine_python_command()} munch.py ../client-{version_id}.jar --output ../burger-{version_id}.json'
)
with open(get_dir_location(f'downloads/burger-{version_id}.json'), 'r') as f:
return json.load(f)
def get_generator_mod_data(version_id: str, category: str):
def get_pixlyzer_data(version_id: str, category: str):
'''
Gets data from u9g's data generator mod. Note that this is not very stable, and it requires Yarn to release updates first.
Gets data from Pixlyzer. Note that this requires Yarn to release updates first.
'''
target_dir = get_dir_location(f'downloads/generator-mod-{version_id}')
target_dir = get_dir_location(f'downloads/pixlyzer-{version_id}')
if not os.path.exists(get_dir_location(target_dir)):
generator_mod_dir = get_generator_mod()
pixlyzer_dir = get_pixlyzer()
yarn_data = get_yarn_data(version_id)
if not yarn_data:
raise Exception(
'Fabric/Yarn hasn\'t been updated to this version yet.')
os.system(f'cd {pixlyzer_dir} && mvn clean -Dmaven.repo.local=. verify')
run_python_command_and_download_deps(
f'cd {pixlyzer_dir}/wrapper && {determine_python_command()} PixLyzer.py --only-version={version_id} --dont-compile'
)
if os.path.exists(target_dir):
os.unlink(target_dir)
os.rename(
get_dir_location(
f'{pixlyzer_dir}/wrapper/data/version/{version_id}'),
target_dir
)
with open(f'{target_dir}/{category}.min.json', 'r') as f:
return json.load(f)
exit()
# looks like 1.19+build.1
yarn_version = yarn_data['version']
@ -104,9 +137,9 @@ def get_generator_mod_data(version_id: str, category: str):
fabric_loader_version = get_fabric_loader_versions()[0]
# the mod has the minecraft version hard-coded by default, so we just change the gradle.properties and fabric.mod.json
with open(get_dir_location(f'{generator_mod_dir}/gradle.properties'), 'r') as f:
with open(get_dir_location(f'{pixlyzer_dir}/gradle.properties'), 'r') as f:
lines = f.readlines()
with open(get_dir_location(f'{generator_mod_dir}/gradle.properties'), 'w') as f:
with open(get_dir_location(f'{pixlyzer_dir}/gradle.properties'), 'w') as f:
for line in lines:
if line.startswith('minecraft_version='):
line = f'minecraft_version={version_id}\n'
@ -118,43 +151,43 @@ def get_generator_mod_data(version_id: str, category: str):
line = f'loader_version={fabric_loader_version}\n'
f.write(line)
# edit the fabric.mod.json to support this version
with open(get_dir_location(f'{generator_mod_dir}/src/main/resources/fabric.mod.json'), 'r') as f:
with open(get_dir_location(f'{pixlyzer_dir}/src/main/resources/fabric.mod.json'), 'r') as f:
fabric_mod_json = json.load(f)
fabric_mod_json['depends']['minecraft'] = '*'
with open(get_dir_location(f'{generator_mod_dir}/src/main/resources/fabric.mod.json'), 'w') as f:
with open(get_dir_location(f'{pixlyzer_dir}/src/main/resources/fabric.mod.json'), 'w') as f:
json.dump(fabric_mod_json, f, indent=2)
try:
os.system(f'cd {generator_mod_dir} && chmod u+x ./gradlew')
os.system(f'cd {pixlyzer_dir} && chmod u+x ./gradlew')
except:
pass
# set the server port to something other than 25565 so it doesn't
# conflict with anything else that's running
try:
os.makedirs(get_dir_location(f'{generator_mod_dir}/run'))
os.makedirs(get_dir_location(f'{pixlyzer_dir}/run'))
except:
pass
with open(get_dir_location(f'{generator_mod_dir}/run/server.properties'), 'w') as f:
with open(get_dir_location(f'{pixlyzer_dir}/run/server.properties'), 'w') as f:
f.write('server-port=56553')
# make sure we have perms to run this file
# (on windows it fails but keeps running)
os.system(f'cd {generator_mod_dir} && chmod u+x ./gradlew')
os.system(f'cd {pixlyzer_dir} && chmod u+x ./gradlew')
try:
subprocess.run(
[f'cd {generator_mod_dir} && ./gradlew runServer'],
[f'cd {pixlyzer_dir} && ./gradlew runServer'],
check=True,
shell=True
)
except Exception as e:
os.system(f'cd {generator_mod_dir} && gradlew runServer')
os.system(f'cd {pixlyzer_dir} && gradlew runServer')
if os.path.exists(target_dir):
os.unlink(target_dir)
os.rename(
get_dir_location(
f'{generator_mod_dir}/run/minecraft-data/{version_id}'),
f'{pixlyzer_dir}/run/minecraft-data/{version_id}'),
target_dir
)