Assets
Dokumentace k práci s herními assety v Hytale.
Obsah
| Soubor | Popis |
|--------|-------|
| MODELS.md | Detailní dokumentace 3D modelů - Model, ModelAsset, ModelComponent, škálování, attachmenty |
| MARKERS.md | World map markery - WorldMapManager, MarkerProvider, MapMarker, vestavěné providery |
---
Struktura Assets
Assets/
├── Server/ # Server-side assety
│ ├── Entity/ # Entity definice
│ ├── NPC/ # NPC definice
│ ├── Item/ # Item definice
│ ├── Drops/ # Drop tabulky
│ └── World/ # World konfigurace
│
└── Common/ # Sdílené assety (client + server)
├── Blocks/ # Block definice
├── Items/ # Item assety
├── UI/ # UI definice
├── Sounds/ # Zvuky
└── VFX/ # Vizuální efekty
---
Asset Registry
Získání Assetu
// Model asset
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset("ModelName");
if (modelAsset != null) {
Model model = Model.createUnitScaleModel(modelAsset);
}// Kontrola existence
if (ModelAsset.getAssetMap().getAsset("MyModel") == null) {
throw new IllegalStateException("Model 'MyModel' not found");
}
LoadedAssetsEvent
Reagování na načtení/změnu assetů:
@Override
protected void setup() {
getEventRegistry().register(LoadedAssetsEvent.class, ModelAsset.class, event -> {
Map loadedModels = event.getLoadedAssets(); ModelAsset myModel = loadedModels.get("MyCustomModel");
if (myModel != null) {
// Model byl načten nebo změněn
this.cachedModel = Model.createUnitScaleModel(myModel);
}
});
}
---
Modely
Vytvoření Model Instance
// Z asset mapy
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset("Warp");
if (modelAsset == null) {
throw new IllegalStateException("Warp model not found");
}// Vytvoření modelu s jednotkovou škálou
Model model = Model.createUnitScaleModel(modelAsset);
// Bounding box
BoundingBox boundingBox = new BoundingBox(model.getBoundingBox());
Přidání Modelu k Entitě
public Holder createEntityWithModel(Model model, Vector3d position) {
Holder holder = EntityStore.REGISTRY.newHolder(); // Pozice
holder.addComponent(
TransformComponent.getComponentType(),
new TransformComponent(position, new Vector3f(0, 0, 0))
);
// Network ID
holder.addComponent(
NetworkId.getComponentType(),
new NetworkId(store.getExternalData().takeNextNetworkId())
);
// Model
holder.addComponent(
ModelComponent.getComponentType(),
new ModelComponent(model)
);
// Bounding box
holder.addComponent(
BoundingBox.getComponentType(),
new BoundingBox(model.getBoundingBox())
);
return holder;
}
---
Warp Entity Příklad
Z TeleportPlugin - vytvoření warp markeru:
@Nonnull
public Holder createWarp(@Nonnull Warp warp, @Nonnull Store store) {
Transform transform = warp.getTransform();
Holder holder = EntityStore.REGISTRY.newHolder(); // Pozice a rotace
holder.addComponent(
TransformComponent.getComponentType(),
new TransformComponent(transform.getPosition(), transform.getRotation())
);
// Network ID pro síťovou synchronizaci
holder.addComponent(
NetworkId.getComponentType(),
new NetworkId(store.getExternalData().takeNextNetworkId())
);
// Nelze s entitou interagovat
holder.ensureComponent(Intangible.getComponentType());
// Bounding box z modelu
holder.addComponent(
BoundingBox.getComponentType(),
new BoundingBox(this.warpModel.getBoundingBox())
);
// 3D model
holder.addComponent(
ModelComponent.getComponentType(),
new ModelComponent(this.warpModel)
);
// Jmenovka
holder.addComponent(
Nameplate.getComponentType(),
new Nameplate(warp.getId())
);
// Skrytá pro adventure hráče
holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType());
// Neserializovat (neperzistovat)
holder.ensureComponent(EntityStore.REGISTRY.getNonSerializedComponentType());
// Vlastní komponenta
holder.addComponent(
this.warpComponentType,
new WarpComponent(warp)
);
return holder;
}
---
Spawn Entity do Světa
// Spawn entity při načtení chunku
private void onChunkPreLoadProcess(ChunkPreLoadProcessEvent event) {
WorldChunk chunk = event.getChunk();
BlockChunk blockChunk = chunk.getBlockChunk(); if (blockChunk == null) return;
int chunkX = blockChunk.getX();
int chunkZ = blockChunk.getZ();
World world = chunk.getWorld();
// Kontrola zda entita patří do tohoto chunku
Vector3d entityPos = getEntityPosition();
if (ChunkUtil.isInsideChunk(chunkX, chunkZ,
MathUtil.floor(entityPos.x),
MathUtil.floor(entityPos.z))) {
// Spawn na world threadu
world.execute(() -> {
Store store = world.getEntityStore().getStore();
Holder holder = createMyEntity(store);
store.addEntity(holder, AddReason.LOAD);
});
}
}
---
World Map Markery
MarkerProvider
public class MyMarkerProvider implements WorldMapManager.MarkerProvider { public static final MyMarkerProvider INSTANCE = new MyMarkerProvider();
@Override
public void update(
@Nonnull World world,
@Nonnull GameplayConfig gameplayConfig,
@Nonnull WorldMapTracker tracker,
int chunkViewRadius,
int playerChunkX,
int playerChunkZ
) {
// Kontrola konfigurace
if (!gameplayConfig.getWorldMapConfig().isDisplayWarps()) {
return;
}
for (MyMarker marker : getMarkers()) {
if (!marker.getWorld().equals(world.getName())) {
continue;
}
tracker.trySendMarker(
chunkViewRadius,
playerChunkX,
playerChunkZ,
marker.getPosition(),
marker.getYaw(),
"Marker-" + marker.getId(),
"Marker: " + marker.getName(),
marker,
(id, name, m) -> new MapMarker(
id,
name,
"MarkerIcon.png",
PositionUtil.toTransformPacket(m.getTransform()),
null
)
);
}
}
}
Registrace Provideru
@Override
protected void setup() {
getEventRegistry().registerGlobal(AddWorldEvent.class, event -> {
World world = event.getWorld();
world.getWorldMapManager().addMarkerProvider("mymarkers", MyMarkerProvider.INSTANCE);
});
}
---
JSON Asset Konfigurace
Assety používají JSON s dědičností:
{
"Parent": "BaseEntity",
"Components": {
"Health": {
"MaxHealth": 100
},
"Movement": {
"Speed": 5.0
}
}
}
Dědičnost
{
"Inherits": "Common/Entities/BaseEnemy",
"Override": {
"Health": {
"MaxHealth": 200
}
}
}
---
Shrnutí
| Operace | Metoda |
|---------|--------|
| Získat model | ModelAsset.getAssetMap().getAsset(name) |
| Vytvořit model | Model.createUnitScaleModel(asset) |
| Reagovat na load | LoadedAssetsEvent |
| Spawn entity | store.addEntity(holder, AddReason.LOAD) |
| World marker | WorldMapManager.addMarkerProvider() |
| Komponenta | Účel |
|------------|------|
| TransformComponent | Pozice a rotace |
| ModelComponent | 3D model |
| BoundingBox | Kolizní box |
| NetworkId | Síťová synchronizace |
| Nameplate | Jmenovka |
| Intangible | Nelze interagovat |