239 lines
11 KiB
Python
239 lines
11 KiB
Python
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"))
|
|
block_kinds = {name: block_kind(archive, name) for name in block_names}
|
|
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)
|
|
merge_language_defaults()
|
|
|
|
inventory = {
|
|
"source": "Warium 1.2.7",
|
|
"source_sha1": "528d81630a23fb4004e3abdd99b16bd225cd1e92",
|
|
"modid": MODID,
|
|
"blocks_from_blockstates": block_names,
|
|
"block_kinds": block_kinds,
|
|
"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)
|
|
write_generated_registries(block_names, block_kinds, standalone_items)
|
|
|
|
|
|
def stem(path: str) -> str:
|
|
return Path(path).name.removesuffix(".json")
|
|
|
|
|
|
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"
|
|
|
|
|
|
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
|
|
|
|
|
|
def write_generated_registries(blocks: list[str], block_kinds: dict[str, str], items: list[str]) -> None:
|
|
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;",
|
|
"",
|
|
"import net.mcreator.crustychunks.CrustyChunksMod;",
|
|
"import net.minecraft.core.Direction;",
|
|
"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;",
|
|
"import net.minecraft.world.item.context.BlockPlaceContext;",
|
|
"import net.minecraft.world.level.block.Block;",
|
|
"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;",
|
|
"import net.minecraft.world.level.block.state.BlockBehaviour;",
|
|
"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;",
|
|
"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)
|
|
kind = block_kinds.get(name, "plain")
|
|
lines.append(f' public static final DeferredHolder<Block, Block> {ident} = BLOCKS.register("{name}", () -> createBlock("{kind}"));')
|
|
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);",
|
|
" }",
|
|
"",
|
|
" 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 {",
|
|
" private GeneratedHorizontalBlock(BlockBehaviour.Properties properties) {",
|
|
" super(properties);",
|
|
" registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH));",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" 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 {",
|
|
" private GeneratedFaceAttachedHorizontalBlock(BlockBehaviour.Properties properties) {",
|
|
" super(properties);",
|
|
" registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(FACE, AttachFace.FLOOR));",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {",
|
|
" builder.add(FACING, FACE);",
|
|
" }",
|
|
" }",
|
|
"}",
|
|
"",
|
|
])
|
|
(package_dir / "GeneratedRegistries.java").write_text("\n".join(lines), encoding="utf-8")
|
|
|
|
|
|
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)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|