2026-05-09 20:59:05 +02:00
from __future__ import annotations
import json
import shutil
import zipfile
from pathlib import Path
from warium_source import MODID , ROOT , clean_dir , download_original , safe_java_identifier , write_json
GENERATED_JAVA = ROOT / " src " / " generated " / " java "
GENERATED_RESOURCES = ROOT / " src " / " generated " / " resources "
INVENTORY_DIR = ROOT / " docs " / " inventory "
def main ( ) - > None :
jar = download_original ( )
clean_dir ( GENERATED_JAVA )
clean_dir ( GENERATED_RESOURCES )
INVENTORY_DIR . mkdir ( parents = True , exist_ok = True )
with zipfile . ZipFile ( jar ) as archive :
names = archive . namelist ( )
block_names = sorted ( stem ( n ) for n in names if n . startswith ( f " assets/ { MODID } /blockstates/ " ) and n . endswith ( " .json " ) )
2026-05-09 23:31:23 +02:00
block_kinds = { name : block_kind ( archive , name ) for name in block_names }
2026-05-09 20:59:05 +02:00
item_model_names = sorted ( stem ( n ) for n in names if n . startswith ( f " assets/ { MODID } /models/item/ " ) and n . endswith ( " .json " ) )
standalone_items = sorted ( name for name in item_model_names if name not in set ( block_names ) )
extract_resources ( archive )
2026-05-09 21:26:11 +02:00
merge_language_defaults ( )
2026-05-09 20:59:05 +02:00
inventory = {
" source " : " Warium 1.2.7 " ,
" source_sha1 " : " 528d81630a23fb4004e3abdd99b16bd225cd1e92 " ,
" modid " : MODID ,
" blocks_from_blockstates " : block_names ,
2026-05-09 23:31:23 +02:00
" block_kinds " : block_kinds ,
2026-05-09 20:59:05 +02:00
" standalone_items_from_item_models " : standalone_items ,
" counts " : {
" blockstates " : len ( block_names ) ,
" item_models " : len ( item_model_names ) ,
" standalone_items " : len ( standalone_items ) ,
" classes " : len ( [ n for n in names if n . endswith ( " .class " ) ] ) ,
" procedures " : len ( [ n for n in names if n . startswith ( " net/mcreator/crustychunks/procedures/ " ) and n . endswith ( " .class " ) ] ) ,
" entities " : len ( [ n for n in names if n . startswith ( " net/mcreator/crustychunks/entity/ " ) and n . endswith ( " .class " ) ] ) ,
" recipes " : len ( [ n for n in names if n . startswith ( f " data/ { MODID } /recipes/ " ) and n . endswith ( " .json " ) ] ) ,
" loot_tables " : len ( [ n for n in names if n . startswith ( f " data/ { MODID } /loot_tables/ " ) and n . endswith ( " .json " ) ] ) ,
} ,
}
write_json ( INVENTORY_DIR / " original-inventory.json " , inventory )
2026-05-09 23:31:23 +02:00
write_generated_registries ( block_names , block_kinds , standalone_items )
2026-05-09 20:59:05 +02:00
def stem ( path : str ) - > str :
return Path ( path ) . name . removesuffix ( " .json " )
2026-05-09 23:31:23 +02:00
def block_kind ( archive : zipfile . ZipFile , name : str ) - > str :
with archive . open ( f " assets/ { MODID } /blockstates/ { name } .json " ) as handle :
data = json . loads ( handle . read ( ) . decode ( " utf-8 " ) )
keys : set [ str ] = set ( )
for variant in data . get ( " variants " , { } ) :
if not variant :
continue
for part in variant . split ( " , " ) :
keys . add ( part . split ( " = " ) [ 0 ] )
if { " facing " , " half " , " hinge " , " open " } . issubset ( keys ) :
return " door "
if { " facing " , " half " , " open " } . issubset ( keys ) :
return " trapdoor "
if { " facing " , " half " , " shape " } . issubset ( keys ) :
return " stairs "
if " type " in keys :
return " slab "
if { " face " , " facing " } . issubset ( keys ) :
return " face_attached "
if " axis " in keys :
return " axis "
if " facing " in keys :
return " horizontal "
return " plain "
2026-05-09 20:59:05 +02:00
def extract_resources ( archive : zipfile . ZipFile ) - > None :
for info in archive . infolist ( ) :
if info . is_dir ( ) :
continue
name = info . filename
if name . startswith ( f " assets/ { MODID } / " ) :
target = GENERATED_RESOURCES / name
elif name . startswith ( f " data/ { MODID } / " ) :
target = GENERATED_RESOURCES / migrate_data_path ( name )
elif name == " pack.mcmeta " :
continue
else :
continue
target . parent . mkdir ( parents = True , exist_ok = True )
with archive . open ( info ) as src , target . open ( " wb " ) as dst :
shutil . copyfileobj ( src , dst )
def migrate_data_path ( path : str ) - > str :
path = path . replace ( f " data/ { MODID } /loot_tables/ " , f " data/ { MODID } /loot_table/ " )
path = path . replace ( f " data/ { MODID } /tags/items/ " , f " data/ { MODID } /tags/item/ " )
path = path . replace ( f " data/ { MODID } /tags/blocks/ " , f " data/ { MODID } /tags/block/ " )
path = path . replace ( f " data/ { MODID } /tags/entity_types/ " , f " data/ { MODID } /tags/entity_type/ " )
path = path . replace ( f " data/ { MODID } /tags/fluids/ " , f " data/ { MODID } /tags/fluid/ " )
return path
2026-05-09 23:31:23 +02:00
def write_generated_registries ( blocks : list [ str ] , block_kinds : dict [ str , str ] , items : list [ str ] ) - > None :
2026-05-09 20:59:05 +02:00
package_dir = GENERATED_JAVA / " net " / " mcreator " / " crustychunks " / " init "
package_dir . mkdir ( parents = True , exist_ok = True )
used : set [ str ] = set ( )
lines : list [ str ] = [
" package net.mcreator.crustychunks.init; " ,
" " ,
2026-05-09 23:37:41 +02:00
" import com.mojang.serialization.MapCodec; " ,
2026-05-09 20:59:05 +02:00
" import net.mcreator.crustychunks.CrustyChunksMod; " ,
2026-05-09 23:31:23 +02:00
" import net.minecraft.core.Direction; " ,
2026-05-09 20:59:05 +02:00
" import net.minecraft.core.registries.Registries; " ,
" import net.minecraft.network.chat.Component; " ,
" import net.minecraft.world.item.BlockItem; " ,
" import net.minecraft.world.item.CreativeModeTab; " ,
" import net.minecraft.world.item.Item; " ,
" import net.minecraft.world.item.ItemStack; " ,
" import net.minecraft.world.item.Items; " ,
2026-05-09 23:31:23 +02:00
" import net.minecraft.world.item.context.BlockPlaceContext; " ,
2026-05-09 20:59:05 +02:00
" import net.minecraft.world.level.block.Block; " ,
2026-05-09 23:31:23 +02:00
" import net.minecraft.world.level.block.Blocks; " ,
" import net.minecraft.world.level.block.DoorBlock; " ,
" import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock; " ,
" import net.minecraft.world.level.block.HorizontalDirectionalBlock; " ,
" import net.minecraft.world.level.block.RotatedPillarBlock; " ,
" import net.minecraft.world.level.block.SlabBlock; " ,
" import net.minecraft.world.level.block.StairBlock; " ,
" import net.minecraft.world.level.block.TrapDoorBlock; " ,
" import net.minecraft.world.level.block.state.BlockState; " ,
2026-05-09 20:59:05 +02:00
" import net.minecraft.world.level.block.state.BlockBehaviour; " ,
2026-05-09 23:31:23 +02:00
" import net.minecraft.world.level.block.state.StateDefinition; " ,
" import net.minecraft.world.level.block.state.properties.AttachFace; " ,
" import net.minecraft.world.level.block.state.properties.BlockSetType; " ,
2026-05-09 20:59:05 +02:00
" import net.neoforged.bus.api.IEventBus; " ,
" import net.neoforged.neoforge.registries.DeferredHolder; " ,
" import net.neoforged.neoforge.registries.DeferredRegister; " ,
" " ,
" public final class GeneratedRegistries { " ,
" public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(Registries.BLOCK, CrustyChunksMod.MODID); " ,
" public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(Registries.ITEM, CrustyChunksMod.MODID); " ,
" public static final DeferredRegister<CreativeModeTab> CREATIVE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, CrustyChunksMod.MODID); " ,
" " ,
]
for name in blocks :
ident = safe_java_identifier ( name , used )
2026-05-09 23:31:23 +02:00
kind = block_kinds . get ( name , " plain " )
lines . append ( f ' public static final DeferredHolder<Block, Block> { ident } = BLOCKS.register( " { name } " , () -> createBlock( " { kind } " )); ' )
2026-05-09 20:59:05 +02:00
lines . append ( f ' public static final DeferredHolder<Item, BlockItem> { ident } _ITEM = ITEMS.register( " { name } " , () -> new BlockItem( { ident } .get(), new Item.Properties())); ' )
for name in items :
ident = safe_java_identifier ( name , used )
lines . append ( f ' public static final DeferredHolder<Item, Item> { ident } = ITEMS.register( " { name } " , () -> new Item(new Item.Properties())); ' )
lines . extend ( [
" " ,
' public static final DeferredHolder<CreativeModeTab, CreativeModeTab> WARIUM_TAB = CREATIVE_TABS.register( " warium " , () -> CreativeModeTab.builder() ' ,
' .title(Component.translatable( " itemGroup.crusty_chunks.warium " )) ' ,
" .icon(() -> new ItemStack(Items.IRON_INGOT)) " ,
" .displayItems((parameters, output) -> ITEMS.getEntries().forEach(entry -> output.accept(entry.get()))) " ,
" .build()); " ,
" " ,
" private GeneratedRegistries() { " ,
" } " ,
" " ,
" public static void register(IEventBus modBus) { " ,
" BLOCKS.register(modBus); " ,
" ITEMS.register(modBus); " ,
" CREATIVE_TABS.register(modBus); " ,
" } " ,
2026-05-09 23:31:23 +02:00
" " ,
" private static Block createBlock(String kind) { " ,
" BlockBehaviour.Properties properties = BlockBehaviour.Properties.of().strength(2.0F, 6.0F); " ,
" return switch (kind) { " ,
' case " axis " -> new RotatedPillarBlock(properties); ' ,
' case " door " -> new DoorBlock(BlockSetType.IRON, properties); ' ,
' case " face_attached " -> new GeneratedFaceAttachedHorizontalBlock(properties); ' ,
' case " horizontal " -> new GeneratedHorizontalBlock(properties); ' ,
' case " slab " -> new SlabBlock(properties); ' ,
' case " stairs " -> new StairBlock(Blocks.STONE.defaultBlockState(), properties); ' ,
' case " trapdoor " -> new TrapDoorBlock(BlockSetType.IRON, properties); ' ,
" default -> new Block(properties); " ,
" }; " ,
" } " ,
" " ,
" private static final class GeneratedHorizontalBlock extends HorizontalDirectionalBlock { " ,
2026-05-09 23:37:41 +02:00
" private static final MapCodec<GeneratedHorizontalBlock> CODEC = simpleCodec(GeneratedHorizontalBlock::new); " ,
" " ,
2026-05-09 23:31:23 +02:00
" private GeneratedHorizontalBlock(BlockBehaviour.Properties properties) { " ,
" super(properties); " ,
" registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH)); " ,
" } " ,
" " ,
" @Override " ,
2026-05-09 23:37:41 +02:00
" protected MapCodec<? extends GeneratedHorizontalBlock> codec() { " ,
" return CODEC; " ,
" } " ,
" " ,
" @Override " ,
2026-05-09 23:31:23 +02:00
" public BlockState getStateForPlacement(BlockPlaceContext context) { " ,
" return defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); " ,
" } " ,
" " ,
" @Override " ,
" protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { " ,
" builder.add(FACING); " ,
" } " ,
" } " ,
" " ,
" private static final class GeneratedFaceAttachedHorizontalBlock extends FaceAttachedHorizontalDirectionalBlock { " ,
2026-05-09 23:37:41 +02:00
" private static final MapCodec<GeneratedFaceAttachedHorizontalBlock> CODEC = simpleCodec(GeneratedFaceAttachedHorizontalBlock::new); " ,
" " ,
2026-05-09 23:31:23 +02:00
" private GeneratedFaceAttachedHorizontalBlock(BlockBehaviour.Properties properties) { " ,
" super(properties); " ,
" registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(FACE, AttachFace.FLOOR)); " ,
" } " ,
" " ,
" @Override " ,
2026-05-09 23:37:41 +02:00
" protected MapCodec<? extends GeneratedFaceAttachedHorizontalBlock> codec() { " ,
" return CODEC; " ,
" } " ,
" " ,
" @Override " ,
2026-05-09 23:31:23 +02:00
" protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { " ,
" builder.add(FACING, FACE); " ,
" } " ,
" } " ,
2026-05-09 20:59:05 +02:00
" } " ,
" " ,
] )
( package_dir / " GeneratedRegistries.java " ) . write_text ( " \n " . join ( lines ) , encoding = " utf-8 " )
2026-05-09 21:26:11 +02:00
def merge_language_defaults ( ) - > None :
lang_path = GENERATED_RESOURCES / " assets " / MODID / " lang " / " en_us.json "
if lang_path . exists ( ) :
data = json . loads ( lang_path . read_text ( encoding = " utf-8 " ) )
else :
data = { }
data . setdefault ( " itemGroup.crusty_chunks.warium " , " Warium " )
write_json ( lang_path , data )
2026-05-09 20:59:05 +02:00
if __name__ == " __main__ " :
main ( )