Blocks & Items
Dokumentace k práci s bloky a itemy v Hytale.
Obsah
| Soubor | Popis |
|--------|-------|
| BLOCK_TYPES.md | BlockType, BlockState, BlockModule, DrawType, BlockMaterial |
| ITEM_STACKS.md | ItemStack, Item assets, Durability, Metadata, Inventory events |
---
Přehled
Blocks & Items System
│
├── BlockType (Asset)
│ ├── DrawType, Material
│ └── BlockEntity, State
│
├── ItemStack (Runtime)
│ ├── Quantity, Durability
│ └── Metadata
│
└── Events
├── BreakBlockEvent
├── PlaceBlockEvent
└── Inventory events
---
Bloky
BlockType
// Získání typu bloku
BlockType blockType = event.getBlockType();// ID bloku
String blockId = blockType.getId();
// Kontrola prázdného bloku (vzduch)
if (blockType == BlockType.EMPTY) {
return; // Přeskoč vzduch
}
BreakBlockEvent
public class BlockBreakSystem extends EntityEventSystem { @Override
public void handle(int i, ArchetypeChunk chunk,
Store store, CommandBuffer buffer,
BreakBlockEvent event) {
// DŮLEŽITÉ: Vždy kontroluj EMPTY
if (event.getBlockType() == BlockType.EMPTY) return;
// Informace o bloku
BlockType blockType = event.getBlockType();
String blockId = blockType.getId();
// Pozice bloku
// BlockPos targetBlock = event.getTargetBlock();
// Nástroj v ruce
// ItemStack itemInHand = event.getItemInHand();
Ref ref = chunk.getReferenceTo(i);
Player player = store.getComponent(ref, Player.getComponentType());
if (player != null) {
player.sendMessage(Message.raw("Rozbit blok: " + blockId));
}
}
@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}
}
PlaceBlockEvent
public class BlockPlaceSystem extends EntityEventSystem { @Override
public void handle(int i, ArchetypeChunk chunk,
Store store, CommandBuffer buffer,
PlaceBlockEvent event) {
Ref ref = chunk.getReferenceTo(i);
Player player = store.getComponent(ref, Player.getComponentType());
if (player != null) {
player.sendMessage(Message.raw("Položen blok"));
// Zrušení položení
// event.cancel();
}
}
@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}
}
UseBlockEvent
public class BlockUseSystem extends EntityEventSystem { @Override
public void handle(int i, ArchetypeChunk chunk,
Store store, CommandBuffer buffer,
UseBlockEvent event) {
// Interakce s blokem (truhla, dveře, tlačítko...)
Ref ref = chunk.getReferenceTo(i);
Player player = store.getComponent(ref, Player.getComponentType());
if (player != null) {
// Zpracování interakce
}
}
@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}
}
---
Block Definice (Assets)
Bloky jsou definovány v Assets/Common/Blocks/:
{
"Id": "stone",
"Name": "Stone",
"Hardness": 1.5,
"BlastResistance": 6.0,
"Drops": [
{
"Item": "cobblestone",
"Count": 1
}
],
"Properties": {
"Solid": true,
"Transparent": false
}
}
Dědičnost
{
"Parent": "base_stone",
"Override": {
"Name": "Granite",
"Texture": "granite.png"
}
}
---
Itemy
ItemStack
// Z eventu
ItemStack itemInHand = event.getItemInHand();// Vlastnosti
String itemId = itemInHand.getItemId();
int count = itemInHand.getCount();
Inventory Eventy
// Změna inventáře
getEventRegistry().register(LivingEntityInventoryChangeEvent.class, event -> {
// Inventář se změnil
});// Crafting
getEventRegistry().register(CraftRecipeEvent.class, event -> {
// Hráč craftí
// event.cancel(); // Zruší crafting
});
// Pickup
getEventRegistry().register(InteractivelyPickupItemEvent.class, event -> {
// Hráč sebral item
});
// Drop
getEventRegistry().register(DropItemEvent.class, event -> {
// Hráč zahodil item
});
---
Item Definice (Assets)
Itemy jsou definovány v Assets/Common/Items/ a Assets/Server/Item/:
{
"Id": "diamond_sword",
"Name": "Diamond Sword",
"Type": "Weapon",
"MaxStackSize": 1,
"Durability": 1561,
"Damage": 7,
"AttackSpeed": 1.6,
"Rarity": "Rare"
}
Typy Itemů
| Typ | Popis |
|-----|-------|
| Weapon | Zbraně |
| Tool | Nástroje |
| Armor | Brnění |
| Consumable | Spotřební (jídlo, lektvary) |
| Block | Položitelné bloky |
| Material | Materiály pro crafting |
| Misc | Ostatní |
---
Container (Inventáře)
Container Komponenta
Z dekompilovaného kódu - kontejnery jsou ECS entity:
// Kontejnery (truhly, inventáře) jsou entity s Container komponentou
Container container = store.getComponent(containerRef, Container.getComponentType());
> "Each item container is associated to an 'entity' in our ECS and they have entity ids... You can register a new component on those container entities" - Slikey
Přidání Vlastní Komponenty ke Kontejneru
// Koncept - přidání vlastní komponenty k truhle
public void onChestCreated(Ref chestRef, Store store) {
// Přidej vlastní data k truhle
store.addComponent(chestRef, MyChestData.getComponentType(), new MyChestData());
}
---
Drops (Loot)
Drop tabulky v Assets/Server/Drops/:
{
"Id": "zombie_drops",
"Entries": [
{
"Item": "rotten_flesh",
"Weight": 100,
"MinCount": 0,
"MaxCount": 2
},
{
"Item": "iron_ingot",
"Weight": 5,
"MinCount": 1,
"MaxCount": 1,
"Conditions": [
{ "Type": "KilledByPlayer" }
]
}
]
}
---
Příklady
Sledování Rozbitých Bloků
public class BlockStatsSystem extends EntityEventSystem { private final Map> blockStats = new ConcurrentHashMap<>();
@Override
public void handle(int i, ArchetypeChunk chunk,
Store store, CommandBuffer buffer,
BreakBlockEvent event) {
if (event.getBlockType() == BlockType.EMPTY) return;
Ref ref = chunk.getReferenceTo(i);
PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType());
if (playerRef != null) {
UUID uuid = playerRef.getUuid();
String blockId = event.getBlockType().getId();
blockStats.computeIfAbsent(uuid, k -> new ConcurrentHashMap<>())
.merge(blockId, 1, Integer::sum);
}
}
public int getBlocksBroken(UUID uuid, String blockId) {
return blockStats.getOrDefault(uuid, Map.of())
.getOrDefault(blockId, 0);
}
@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}
}
Ochrana Bloků
public class BlockProtectionSystem extends EntityEventSystem { private final Set protectedBlocks = ConcurrentHashMap.newKeySet();
@Override
public void handle(int i, ArchetypeChunk chunk,
Store store, CommandBuffer buffer,
BreakBlockEvent event) {
if (event.getBlockType() == BlockType.EMPTY) return;
// Získej pozici bloku
// Vector3i blockPos = event.getTargetBlock().toVector3i();
// if (protectedBlocks.contains(blockPos)) {
// Ref ref = chunk.getReferenceTo(i);
// Player player = store.getComponent(ref, Player.getComponentType());
//
// if (player != null) {
// player.sendMessage(Message.raw("Tento blok je chráněný!"));
// }
//
// event.cancel();
// }
}
public void protectBlock(Vector3i position) {
protectedBlocks.add(position);
}
public void unprotectBlock(Vector3i position) {
protectedBlocks.remove(position);
}
@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}
}
---
Shrnutí
| Event | Popis | Cancellable |
|-------|-------|-------------|
| BreakBlockEvent | Rozbití bloku | Ano |
| PlaceBlockEvent | Položení bloku | Ano |
| UseBlockEvent | Použití bloku | Ano |
| DamageBlockEvent | Poškození bloku | Ano |
| Inventory Event | Popis |
|-----------------|-------|
| LivingEntityInventoryChangeEvent | Změna inventáře |
| CraftRecipeEvent | Crafting |
| InteractivelyPickupItemEvent | Sebrání itemu |
| DropItemEvent | Zahození itemu |
| Kontrola | Kód |
|----------|-----|
| Prázdný blok | event.getBlockType() == BlockType.EMPTY |
| ID bloku | event.getBlockType().getId() |