Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blocks: add version-dependent block states, fixes #467 #469

Merged
merged 17 commits into from
Jan 14, 2021
Merged

Conversation

iceiix
Copy link
Owner

@iceiix iceiix commented Jan 11, 2021

debugging #467

@iceiix
Copy link
Owner Author

iceiix commented Jan 11, 2021

Run with:

DEBUG_BLOCKS=1 cargo run --release

and look for block state output. A quick script to clean up the output:

#!/usr/local/bin/python3
# parse output of steven_blocks with DEBUG_BLOCKS=1
import sys
import re

blocks={}
for line in open("steven_blocks.txt").readlines(): #sys.stdin.readlines():
    match = re.match(r"^(\d+) block state = (\S+)(.*)", line)
    if not match: continue
    id, name, data = match.groups()
    id = int(id)

    if name not in blocks: blocks[name] = {}
    blocks[name][id] = data

#import pprint; pprint.pprint(blocks)

startingIDs={}
for name in blocks.keys():
    minStateID = min(blocks[name].keys())
    maxStateID = max(blocks[name].keys())

    #print(name,minStateID,maxStateID)
    startingIDs[minStateID] = (name, maxStateID)

for minStateID in sorted(startingIDs.keys()):
    name, maxStateID = startingIDs[minStateID]

    print("%d-%d %s" % (minStateID,maxStateID,name))

spot checked some of the values vs #467 (comment), the last one StructureBlock is 8595-8598, this is correct for 1.13.2 but not any other versions:

name	1.13	1.13.2	1.14.4	1.15.2	1.16.1	1.16.2
Structure Block	8578-8581	8595-8598**	11252-11255**	11268-11271**	15735-15738**	15743-15746**	

we don't support protocol 1.13 (protocol support: #18), but do support 1.13.2 (added in iceiix/steven#67 #67), 1.14, 1.14.1, 1.14.2, 1.14.3, 1.14.4; 1.15.1, 1.15.2; 1.16.1, and 1.16.2(/3/4). Presumably minecraft-data's 1.14.4 applies to all of 1.14.x etc., or were new block states actually added in the .4 update? No, this is merely how they are stored, https://github.com/PrismarineJS/minecraft-data/blob/master/data/dataPaths.json has the paths, "1.14": { "blocks": "pc/1.14.4", and so on:

  • 1.13.2 = 1.13.2
  • 1.14 = 1.14.4
  • 1.14.1 = 1.14.4
  • 1.14.2 not listed in minecraft-data
  • 1.14.3 = 1.14.4
  • 1.14.4 = 1.14.4
  • 1.15 = 1.15.2
  • 1.15.1 = 1.15.2
  • 1.15.2 = 1.15.2
  • 1.16.1 = 1.16.1
  • 1.16.2 = 1.16.2

so the initial protocol versions we support, for each of the new sets of blocks would be:

  • 1.13.2+ (protocol_version >= 404), use blocks states from 1.13.2 (currently supported)
  • 1.14+ (protocol_version >= 477), use new block states from 1.14.4
    • v18w50a (451) and v19w02a (452) are also supported, 1.14 snapshots, both add new blocks so they may shift ids too, fortunately the released updates of this major version do not
  • 1.15 (protocol_version >= 575), use new block states from 1.15.2
  • 1.16.1 (protocol_version >= 735), use new block states from 1.16.1
  • 1.16.2+ (protocol_version >= 751), use new block states from 1.16.2

Are block states only additive? If so, considering adding a min_protocol_version token to the define_blocks! macro

@iceiix
Copy link
Owner Author

iceiix commented Jan 11, 2021

Script to dump the block state ranges from minecraft-data, for comparison to the above parsed DEBUG_BLOCKS output:

#!/usr/local/bin/python3
# List block state ranges
import json

versions=('1.13','1.13.2','1.14.4','1.15.2','1.16.1','1.16.2')
block2versions={}
minStates={}
for v in versions:
    blocks=json.load(open('data/pc/'+v+'/blocks.json'))
    for block in blocks:
        #block['id']
        #print(v,block['displayName'], block['minStateId'], block['maxStateId'])
        name=block['displayName']
        if name not in block2versions: block2versions[name] = {}
        block2versions[name][v] = range(block['minStateId'], block['maxStateId'])

        if v not in minStates: minStates[v]={}
        minStates[v][block['minStateId']] = (name, block['maxStateId'])

v = '1.13.2'
for minState in sorted(minStates[v].keys()):
    name, maxState = minStates[v][minState]

    print("%d-%d %s"%(minState,maxState,name))

Not quite directly comparable because of the 1) identifier naming vs display naming, and 2) tighter block state packing within steven_blocks:

Screen Shot 2021-01-10 at 8 01 35 PM

but it looks right for 1.13.2, at least the high-level groupings. 1.14.4 (which really means 1.14+) there is a huge shift due to Note Block expanding from 248-747 (500 states) to 248-1047 (800 states):

Screen Shot 2021-01-10 at 8 04 27 PM

diffing the state count could be a reasonable way to see changes, this gets close (shows the note block expansion, new flower blocks, renamed redstone, but something odd starts going on with signs):

 1 Sandstone
 1 Chiseled Sandstone
 1 Cut Sandstone
-500 Note Block
+800 Note Block
 16 White Bed
 16 Orange Bed
 16 Magenta Bed
@@ -126,6 +126,9 @@
 1 White Tulip
 1 Pink Tulip
 1 Oxeye Daisy
+1 Cornflower
+1 Wither Rose
+1 Lily of the Valley
 1 Brown Mushroom
 1 Red Mushroom
 1 Block of Gold
@@ -141,7 +144,7 @@
 1 Spawner
 80 Oak Stairs
 24 Chest
-1296 Redstone Dust
+1296 Redstone Wire
 1 Diamond Ore
 1 Block of Diamond
 1 Crafting Table
@@ -149,11 +152,21 @@
 8 Farmland
 8 Furnace
 32 Sign
+32 Sign
+32 Sign
+32 Sign
+32 Sign
+32 Sign
 64 Oak Door
 8 Ladder
 10 Rail
 80 Cobblestone Stairs
 8 Wall Sign
+8 Wall Sign
+8 Wall Sign
+8 Wall Sign
+8 Wall Sign
+8 Wall Sign
...

bigger diff: https://gist.github.com/iceiix/158686a6b1754873223c141908505932

Looking further down the list, it does appear some blocks are moved (?):

+1 Stone Bricks
+1 Mossy Stone Bricks
+1 Cracked Stone Bricks
+1 Chiseled Stone Bricks
 1 Infested Stone
 1 Infested Cobblestone
 1 Infested Stone Bricks
 1 Infested Mossy Stone Bricks
 1 Infested Cracked Stone Bricks
 1 Infested Chiseled Stone Bricks
-1 Stone Bricks
-1 Mossy Stone Bricks
-1 Cracked Stone Bricks
-1 Chiseled Stone Bricks

also dead coral wall fans. Near the end (good), 56 new blocks are added

@iceiix
Copy link
Owner Author

iceiix commented Jan 12, 2021

Refactored by_vanilla_id to be a method of VanillaIDMap, held by World, initialized with the protocol version (this is already cleaner than before where the protocol_version had to be passed to each call of by_vanilla_id). Started trying to add protocol_version-specific block states, but this fails:

        offset instrument.offset(protocol_version)
            .map(|offset| offset * (25 * 2) + ((note as usize) << 1) + if powered { 0 } else { 1 }),
error[E0425]: cannot find value `protocol_version` in this scope
   --> blocks/src/lib.rs:873:34
    |
873 |         offset instrument.offset(protocol_version)
    |                                  ^^^^^^^^^^^^^^^^ not found in this scope

error: aborting due to previous error

Why isn't it in scope? $offsetfunc is matched as an expression in:

                $(offset $offsetfunc:expr,)?

then expanded here, where I pass protocol_version as a method parameter, but $offsetfunc can't see it:

            pub fn get_flat_offset(&self, protocol_version: i32) -> Option<usize> {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)?
                        } => {
                            $(
                                let offset: Option<usize> = ($offsetfunc).map(|v| v);
                                return offset;
                            )?
                            $(
                                let data: Option<usize> = ($datafunc).map(|v| v);
                                return data;
                            )?
                            Some(0)
                        }
                    )+
                }
            }

reduced:

macro_rules! define_blocks {
    (
        $(
            $name:ident {
                props {
                    $(
                        $fname:ident : $ftype:ty = [$($val:expr),+],
                    )*
                },
                $(offset $offsetfunc:expr,)?
            }
        )+
    ) => (
        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
        pub enum Block {
            $(
                $name {
                    $(
                        $fname : $ftype,
                    )?
                },
            )+
        }
        impl Block {
            #[allow(unused_variables, unreachable_code)]
            pub fn get_flat_offset(&self, protocol_version: i32) -> Option<usize> {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)?
                        } => {
                            $(
                                println!("offsetfunc = {:?}", $offsetfunc);
                                let offset: Option<usize> = ($offsetfunc).map(|v| v);
                                return offset;
                            )?
                            Some(0)
                        }
                    )+
                }
            }
        }
    )
}

define_blocks! {
    NoteBlock {
        props {
            note: usize = [0, 1, 2, 3],
        },
        offset Some(note),
        //offset Some(protocol_version),
    }
}

fn main() {
    let b = Block::NoteBlock { note: 2 };
    println!("{:?}", b);
    println!("{:?}", b.get_flat_offset(404));
}

with rustc +nightly a.rs -Z macro-backtrace and #![feature(trace_macros)] trace_macros!(true);, expands to:

   = note: expanding `define_blocks! { NoteBlock
           { props { note : i32 = [0, 1, 2, 3], }, offset Some(protocol_version), } }`
   = note: to `#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Block
           { NoteBlock { note : i32, }, } impl Block
           {
               #[allow(unused_variables, unreachable_code)] pub fn
               get_flat_offset(& self, protocol_version : i32) -> Option < i32 >
               {
                   match * self
                   {
                       Block :: NoteBlock { note, } =>
                       {
                           let offset : Option < i32 > = (Some(protocol_version)) .
                           map(| v | v) ; return offset ; Some(0)
                       }
                   }
               }
           }`

and this macro output does compile if copied into a new file, but not from the macro. Maybe from https://veykril.github.io/tlborm/macros/minutiae/hygiene.html

That said, tokens that were substituted into the expanded output retain their original syntax context (by virtue of having been provided to the macro as opposed to being part of the macro itself). Thus, the solution is to modify the macro as follows:

macro_rules! using_a {
    ($a:ident, $e:expr) => {
        {
            let $a = 42;
            $e
        }
    }
}

which explains why note matched, because it was matched from $fname:ident earlier in the macro

@iceiix iceiix changed the title blocks: add DEBUG_BLOCKS environment variable to dump block states blocks: add version-dependent block states Jan 14, 2021
@iceiix iceiix changed the title blocks: add version-dependent block states blocks: add version-dependent block states, fixes #467 Jan 14, 2021
@iceiix
Copy link
Owner Author

iceiix commented Jan 14, 2021

Adding version-dependent block states for the note block, 1.14.4 grass now is shown correctly:

Screen Shot 2021-01-13 at 4 12 45 PM

and 1.13.2 grass still works too (because the new noteblock blockstates are conditionalized on protocol_version >= 477
.... now to update the other block states

@iceiix
Copy link
Owner Author

iceiix commented Jan 14, 2021

Added many block variants to 1.14+, fixing offsets, 1.14.4 is looking not too bad:

Screen Shot 2021-01-13 at 6 50 55 PM

but not all blocks are added. Added up to the stone slab variants, left off here: https://gist.github.com/iceiix/158686a6b1754873223c141908505932#file-gistfile1-txt-L123 before the coral wall fan changes:

@@ -569,16 +588,6 @@
 2 Bubble Coral
 2 Fire Coral
 2 Horn Coral
-8 Dead Tube Coral Wall Fan
-8 Dead Brain Coral Wall Fan
-8 Dead Bubble Coral Wall Fan
-8 Dead Fire Coral Wall Fan
-8 Dead Horn Coral Wall Fan
-8 Tube Coral Wall Fan
-8 Brain Coral Wall Fan
-8 Bubble Coral Wall Fan
-8 Fire Coral Wall Fan
-8 Horn Coral Wall Fan
 2 Dead Tube Coral Fan
 2 Dead Brain Coral Fan
 2 Dead Bubble Coral Fan
@@ -589,10 +598,79 @@
 2 Bubble Coral Fan
 2 Fire Coral Fan
 2 Horn Coral Fan
+8 Dead Tube Coral Wall Fan
+8 Dead Brain Coral Wall Fan
+8 Dead Bubble Coral Wall Fan
+8 Dead Fire Coral Wall Fan
+8 Dead Horn Coral Wall Fan
+8 Tube Coral Wall Fan
+8 Brain Coral Wall Fan
+8 Bubble Coral Wall Fan
+8 Fire Coral Wall Fan
+8 Horn Coral Wall Fan
 8 Sea Pickle
 1 Blue Ice
 2 Conduit
+1 Bamboo Sapling
+12 Bamboo
+1 Flower Pot
 1 Void Air
 1 Cave Air
 2 Bubble Column
+80 Polished Granite Stairs
+80 Smooth Red Sandstone Stairs
+80 Mossy Stone Brick Stairs
+80 Polished Diorite Stairs
+80 Mossy Cobblestone Stairs
+80 End Stone Brick Stairs
+80 Stone Stairs
+80 Smooth Sandstone Stairs
+80 Smooth Quartz Stairs
+80 Granite Stairs
+80 Andesite Stairs
+80 Nether Brick Stairs
+80 Polished Andesite Stairs
+80 Diorite Stairs
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Stone Slab
+6 Nether Brick Slab
+6 Stone Slab
+6 Stone Slab
+64 Brick Wall
+64 Prismarine Wall
+64 Red Sandstone Wall
+64 Mossy Stone Brick Wall
+64 Granite Wall
+64 Stone Brick Wall
+64 Nether Brick Wall
+64 Andesite Wall
+64 Red Nether Brick Wall
+64 Sandstone Wall
+64 End Stone Brick Wall
+64 Diorite Wall
+32 Scaffolding
+4 Loom
+12 Barrel
+8 Smoker
+8 Blast Furnace
+1 Cartography Table
+1 Fletching Table
+12 Grindstone
+16 Lectern
+1 Smithing Table
+4 Stonecutter
+16 Bell
+2 Lantern
+32 Campfire
+4 Sweet Berry Bush
 4 Structure Block
+6 Jigsaw Block
+9 Composter

not to mention the post-1.14 block changes:

  • 1.15 (protocol_version >= 575), use new block states from 1.15.2
  • 1.16.1 (protocol_version >= 735), use new block states from 1.16.1
  • 1.16.2+ (protocol_version >= 751), use new block states from 1.16.2

but this pull request is still better than before, will merge it for now

@iceiix
Copy link
Owner Author

iceiix commented Jan 14, 2021

1.16.4 is also no longer on fire (though still not completely correct blocks, it is an improvement):

Screen Shot 2021-01-13 at 7 05 10 PM

@iceiix iceiix merged commit 8ca12a6 into master Jan 14, 2021
@iceiix iceiix deleted the blockstate branch January 14, 2021 03:50
iceiix added a commit that referenced this pull request Jan 15, 2021
Adds _some _new blocks and block states, building on the version-
dependent block support added in #469. Notably, fixes grass on 1.16.4.

1.16.1+ (protocol_version >= 735)
* Add NetherGoldOre
* Add SoulFire
* Add SoulSoil, Basalt
* Add PolishedBasalt, SoulTorch, SoulWallTorch
* Add Chain

* 1.16.2+ (protocol_version >= 751)
* Add Chain axis states
iceiix added a commit that referenced this pull request Jan 15, 2021
Adds _some _new blocks and block states, building on the version-
dependent block support added in #469. Notably, fixes grass on 1.16.4.

1.16.1+ (protocol_version >= 735)
* Add NetherGoldOre
* Add SoulFire
* Add SoulSoil, Basalt
* Add PolishedBasalt, SoulTorch, SoulWallTorch
* Add Chain

* 1.16.2+ (protocol_version >= 751)
* Add Chain axis states
iceiix added a commit that referenced this pull request Jan 15, 2021
Adds _some _new blocks and block states, building on the version-
dependent block support added in #469. Notably, fixes grass on 1.16.4.

1.16.1+ (protocol_version >= 735)
* Add NetherGoldOre
* Add SoulFire
* Add SoulSoil, Basalt
* Add PolishedBasalt, SoulTorch, SoulWallTorch
* Add Chain

1.16.2+ (protocol_version >= 751)
* Add Chain axis states
iceiix added a commit that referenced this pull request Jan 21, 2021
iceiix added a commit that referenced this pull request Jan 21, 2021
* blocks: fix soul fire/soil, exclude from <1.13, fixing #489 

* blocks: add unit tests for #467 #469 #474
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant