Created
December 21, 2020 16:02
-
-
Save Podshot/6b423009c101599125b03fba5d333072 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from enum import IntFlag | |
from typing import List | |
from collections.abc import Mapping, MutableSequence | |
from pprint import pprint | |
from dataclasses import dataclass | |
from uuid import UUID | |
def flatten_nbt(data): | |
def walk(path, node, store=None): | |
if not store: | |
store = {} | |
for key, item in node.items(): | |
entry_key = f"{path}{'.' if path else ''}{key}".lower() | |
if isinstance(item, Mapping): | |
walk(entry_key, item, store) | |
elif isinstance(item, MutableSequence): | |
ls = [] | |
for element in item: | |
if isinstance(element, Mapping): | |
ls.append(walk("", element)) | |
else: | |
ls.append(element) | |
store[entry_key] = ls | |
else: | |
store[entry_key] = item | |
return store | |
return walk("item", data) | |
class ItemFactory: | |
def __init__(self): | |
pass | |
def load(self, item_nbt) -> Item: | |
raise NotImplementedError() | |
def save(self, item: Item): | |
raise NotImplementedError() | |
class ItemStructures: | |
class HideFlags(IntFlag): | |
ENCHANTMENTS = 1 | |
ATTRIBUTE_MODIFIERS = 2 | |
UNBREAKABLE = 4 | |
CAN_DESTROY = 8 | |
CAN_PLACE_ON = 16 | |
MISC = 32 | |
DYED = 64 | |
@dataclass | |
class Enchantment: | |
id: str = None | |
lvl: int = None | |
@dataclass | |
class Display: | |
name: str = None | |
color: int = None | |
lore: List[str] = None | |
@staticmethod | |
def parse_color(red, green, blue) -> int: | |
return (red << 16) + (green << 8) + blue | |
@staticmethod | |
def from_color(color): | |
blue = color & 0xFF | |
green = (color >> 8) & 0xFF | |
red = (color >> 16) & 0xFF | |
return red, green, blue | |
@dataclass | |
class AttributeModifier: | |
attribute_name: str = None | |
name: str = None | |
slot: str = None | |
operation: int = None | |
amount: float = None | |
uuid: UUID = None | |
class ItemValue: | |
def __init__(self, value=None, children=None, func_pointer=None): | |
if value is None and children is None: | |
raise Exception("ItemValue must have a value or children") | |
if value and children: | |
raise Exception("ItemValue cannot have both a value and children") | |
self._value = value | |
self._children = children | |
self._func_pointer = func_pointer | |
@property | |
def value(self): | |
return self._value | |
@value.setter | |
def value(self, val): | |
self._func_pointer(val) | |
@property | |
def children(self): | |
return self._children | |
class Item: | |
def __init__(self, item_data): | |
self._item_data = item_data | |
def _set_data(self, path, value): | |
self._item_data[path] = value | |
def __getitem__(self, item): | |
if item in self._item_data: | |
return ItemValue( | |
value=self._item_data[item], | |
func_pointer=lambda v: self._set_data(item, v), | |
) | |
return ItemValue( | |
children=list(filter(lambda k: k.startswith(item), self._item_data.keys())), | |
func_pointer=lambda v: self._set_data(item, v), | |
) | |
if __name__ == "__main__": | |
i1 = { | |
"id": "minecraft:stick", | |
"tag": { | |
"Damage": 10, | |
"Unbreakable": 0, | |
"Enchantments": [ | |
{"id": "aqua_affinity", "lvl": 1}, | |
{"id": "enchant", "lvl": 100}, | |
], | |
"test": [0, 1, 2], | |
"test_nested": [ | |
{ | |
"id": "test1", | |
"values": [3, 4, 5], | |
"nested": {"foo": "bar", "vals": [6, 7, 8]}, | |
}, | |
{ | |
"id": "test2", | |
"values": [3.5, 4.5, 5.5], | |
"nested": {"foo": "var", "vals": [6.5, 7.5, 8.5]}, | |
}, | |
], | |
}, | |
} | |
pprint(flatten_nbt(i1)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from common import ItemFactory, flatten_nbt, Item, ItemStructures | |
class Anvil2ItemFactory(ItemFactory): | |
def load(self, item_nbt) -> Item: | |
flattened = flatten_nbt(item_nbt) | |
if "item.tag.enchantments" in flattened: | |
flattened["item.tag.enchantments"] = [ | |
ItemStructures.Enchantment(id=enchant["id"], lvl=enchant["lvl"]) | |
for enchant in flattened["item.tag.enchantments"] | |
] | |
if "item.tag.display" in flattened: | |
flattened["item.tag.display"] = ItemStructures.Display( | |
color=flattened.get("item.tag.display.color", None), | |
name=flattened.get("item.tag.display.Name", None), | |
lore=flattened.get("item.tag.display.Lore", None) | |
) | |
return Item(flattened) | |
def save(self, item: Item): | |
raise NotImplementedError | |
if __name__ == "__main__": | |
factory = Anvil2ItemFactory() | |
item = factory.load( | |
{ | |
"id": "minecraft:stick", | |
"tag": { | |
"Damage": 10, | |
"Unbreakable": 0, | |
"Enchantments": [ | |
{"id": "aqua_affinity", "lvl": 1}, | |
{"id": "enchant", "lvl": 100}, | |
], | |
"test": [0, 1, 2], | |
"test_nested": [ | |
{ | |
"id": "test1", | |
"values": [3, 4, 5], | |
"nested": {"foo": "bar", "vals": [6, 7, 8]}, | |
}, | |
{ | |
"id": "test2", | |
"values": [3.5, 4.5, 5.5], | |
"nested": {"foo": "var", "vals": [6.5, 7.5, 8.5]}, | |
}, | |
], | |
}, | |
} | |
) | |
print(item._item_data) | |
print(item['item.tag.doesnt_exist1.doesnt_exist2'].value) | |
item['item.tag.doesnt_exist1.doesnt_exist2'].value = 4 | |
print(item['item.tag.doesnt_exist1.doesnt_exist2'].children) | |
print(item['item.tag.doesnt_exist1.doesnt_exist2'].value) | |
print(item['item.tag'].children) | |
print() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment