HyCodeYourTale

Initialization

Initialization

Dokumentace inicializace pluginu - registry, komponenty a vzory.

---

Dostupné Registry

Z PluginBase (dekompilovaný kód):

public abstract class PluginBase {
// Command registry pro příkazy
private final CommandRegistry commandRegistry;

// Event registry pro event listenery
private final EventRegistry eventRegistry;

// Block state registry
private final BlockStateRegistry blockStateRegistry;

// Entity registry
private final EntityRegistry entityRegistry;

// Task registry pro periodické úlohy
private final TaskRegistry taskRegistry;

// ECS komponenty pro entity
private final ComponentRegistryProxy entityStoreRegistry;

// ECS komponenty pro chunky
private final ComponentRegistryProxy chunkStoreRegistry;

// Asset registry
private final AssetRegistry assetRegistry;

// Codec registry
private final Map, IRegistry> codecMapRegistries;

// Client feature registry
private final ClientFeatureRegistry clientFeatureRegistry;
}

Gettery

getCommandRegistry();           // CommandRegistry
getEventRegistry(); // EventRegistry
getBlockStateRegistry(); // BlockStateRegistry
getEntityRegistry(); // EntityRegistry
getTaskRegistry(); // TaskRegistry
getEntityStoreRegistry(); // ComponentRegistryProxy
getChunkStoreRegistry(); // ComponentRegistryProxy
getAssetRegistry(); // AssetRegistry
getClientFeatureRegistry(); // ClientFeatureRegistry
getCodecRegistry(mapCodec); // CodecMapRegistry

---

Registrace Komponent

EntityStore Komponenty

@Override
protected void setup() {
// Registrace nové komponenty
this.myComponentType = getEntityStoreRegistry().registerComponent(
MyComponent.class,
MyComponent::new // Factory
);
}

// Použití komponenty
MyComponent comp = store.getComponent(ref, myComponentType);
store.addComponent(ref, myComponentType, new MyComponent());

ChunkStore Komponenty

@Override
protected void setup() {
// Registrace komponenty pro chunky
this.chunkDataType = getChunkStoreRegistry().registerComponent(
ChunkData.class,
ChunkData::new
);
}

Manuální Komponenty

Pro komponenty které nelze automaticky vytvářet:

@Override
protected void setup() {
this.warpComponentType = getEntityStoreRegistry().registerComponent(
WarpComponent.class,
() -> {
throw new UnsupportedOperationException("WarpComponent must be created manually");
}
);
}

// Použití
holder.addComponent(warpComponentType, new WarpComponent(warp));

---

Registrace Systémů

ECS Systémy

@Override
protected void setup() {
// Registrace systému
getEntityStoreRegistry().registerSystem(new MyDeathHandlerSystem());
getEntityStoreRegistry().registerSystem(new MyDamageSystem());
}

Příklad Systému

public class MyDeathHandlerSystem extends RefChangeSystem {
private final ComponentType deadType = Dead.getComponentType();
private final Query query = Query.and(deadType, Player.getComponentType());

@Override
public Query getQuery() {
return query;
}

@Override
public ComponentType componentType() {
return deadType;
}

@Override
public void onComponentAdded(
Ref ref,
Dead component,
Store store,
CommandBuffer commandBuffer
) {
// Hráč zemřel
handleDeath(ref, store);
}
}

---

Registrace Příkazů

Základní Registrace

@Override
protected void setup() {
CommandRegistry registry = getCommandRegistry();

registry.registerCommand(new MyCommand());
registry.registerCommand(new AnotherCommand());
registry.registerCommand(new AdminCommand());
}

Příklad Příkazu

public class MyCommand extends CommandBase {
public MyCommand() {
super("mycommand", "server.commands.mycommand.desc");
requirePermission(HytalePermissions.fromCommand("mycommand"));
}

@Override
protected void executeSync(CommandContext context) {
context.sendMessage(Message.raw("Hello!"));
}
}

---

Registrace Eventů

Synchronní Eventy

@Override
protected void setup() {
EventRegistry registry = getEventRegistry();

// Globální event (všechny světy)
registry.registerGlobal(PlayerReadyEvent.class, this::onPlayerReady);

// World-specific event
registry.registerGlobal(AddWorldEvent.class, event -> {
World world = event.getWorld();
initializeWorld(world);
});

// All worlds loaded
registry.registerGlobal(AllWorldsLoadedEvent.class, event -> {
loadGlobalData();
});
}

private void onPlayerReady(PlayerReadyEvent event) {
Player player = event.getPlayer();
loadPlayerData(player);
}

Asynchronní Eventy

@Override
protected void setup() {
EventRegistry registry = getEventRegistry();

// Async event
registry.registerAsyncGlobal(PlayerChatEvent.class, future -> {
future.thenAccept(event -> {
onPlayerChat(event);
});
});
}

Asset Eventy

@Override
protected void setup() {
EventRegistry registry = getEventRegistry();

// Když se načte asset
registry.register(LoadedAssetsEvent.class, ModelAsset.class, event -> {
Map models = event.getLoadedAssets();
processModels(models);
});
}

---

Registrace Assetů

Asset Map

@Override
protected void setup() {
AssetRegistry registry = getAssetRegistry();

registry.registerAssetMap(MyAsset.class, myAssetMap);
}

Codec Registry

@Override
protected void setup() {
// Registrace vlastního codeku
getCodecRegistry(MyAsset.CODEC_MAP).registerCodec("custom", CustomCodec.INSTANCE);
}

---

Config System

Definice Config Třídy

public class MyConfig {
private boolean debug = false;
private int maxItems = 100;
private String welcomeMessage = "Welcome!";

public static final BuilderCodec CODEC;

static {
BuilderCodec.Builder builder = BuilderCodec.builder(MyConfig.class, MyConfig::new);

builder.append(new KeyedCodec<>("Debug", Codec.BOOLEAN), MyConfig::setDebug, MyConfig::isDebug)
.defaultValue(false)
.add();

builder.append(new KeyedCodec<>("MaxItems", Codec.INTEGER), MyConfig::setMaxItems, MyConfig::getMaxItems)
.defaultValue(100)
.add();

builder.append(new KeyedCodec<>("WelcomeMessage", Codec.STRING), MyConfig::setWelcomeMessage, MyConfig::getWelcomeMessage)
.defaultValue("Welcome!")
.add();

CODEC = builder.build();
}

// Gettery a settery...
public boolean isDebug() { return debug; }
public void setDebug(boolean debug) { this.debug = debug; }
public int getMaxItems() { return maxItems; }
public void setMaxItems(int maxItems) { this.maxItems = maxItems; }
public String getWelcomeMessage() { return welcomeMessage; }
public void setWelcomeMessage(String msg) { this.welcomeMessage = msg; }
}

Použití v Pluginu

public class MyPlugin extends JavaPlugin {
private final Config config;

public MyPlugin(JavaPluginInit init) {
super(init);
// Musí být v konstruktoru!
this.config = withConfig(MyConfig.CODEC);
}

@Override
protected void setup() {
// Config je již načtený díky preLoad()
MyConfig cfg = config.get();

if (cfg.isDebug()) {
getLogger().atInfo().log("Debug mode enabled");
}
}

public MyConfig getConfig() {
return config.get();
}
}

---

Singleton Pattern

Standard Pattern

public class MyPlugin extends JavaPlugin {
private static MyPlugin instance;

public MyPlugin(JavaPluginInit init) {
super(init);
}

@Nonnull
public static MyPlugin get() {
return instance;
}

@Override
protected void setup() {
instance = this; // Nastav singleton v setup()
// ...
}

// Gettery pro ComponentType
public ComponentType getMyComponentType() {
return myComponentType;
}
}

Použití

// Kdekoliv v kódu
MyPlugin plugin = MyPlugin.get();
MyComponent comp = store.getComponent(ref, MyPlugin.get().getMyComponentType());

---

Task Registry

Periodické Úlohy

@Override
protected void setup() {
TaskRegistry taskRegistry = getTaskRegistry();

// Registrace periodické úlohy
taskRegistry.registerTask("save-data", () -> {
saveAllData();
}, 5, TimeUnit.MINUTES); // Každých 5 minut
}

---

Identifikace Pluginu

PluginIdentifier

// Získání identifikátoru
PluginIdentifier id = getIdentifier();

// String reprezentace
String idString = id.toString(); // "group:name"

PluginManifest

PluginManifest manifest = getManifest();

String name = manifest.getName();
String version = manifest.getVersion();
String group = manifest.getGroup();
boolean hasAssets = manifest.includesAssetPack();

---

Data Directory

Cesta k Datům

// Složka pluginu
Path dataDir = getDataDirectory();

// Příklad cest
Path configPath = dataDir.resolve("config.json");
Path dataPath = dataDir.resolve("data/players.json");

// Vytvoření složek
Files.createDirectories(dataDir.resolve("data"));

---

Logger

HytaleLogger API

// Info
getLogger().atInfo().log("Message");
getLogger().atInfo().log("Message with %s and %d", param1, param2);

// Warning
getLogger().atWarning().log("Warning message");

// Severe s výjimkou
getLogger().at(Level.SEVERE).withCause(exception).log("Error occurred:");

// Debug (pokud je debug mode)
getLogger().atFine().log("Debug info");

---

Kompletní Příklad Inicializace

public class ExamplePlugin extends JavaPlugin {

private static ExamplePlugin instance;

// Komponenty
private ComponentType playerStatsType;
private ComponentType customDataType;

// Config
private final Config config;

// Cache
private final Map playerCache = new ConcurrentHashMap<>();

// Konstruktor
public ExamplePlugin(JavaPluginInit init) {
super(init);
this.config = withConfig(ExampleConfig.CODEC);
}

// Singleton
public static ExamplePlugin get() {
return instance;
}

@Override
protected void setup() {
instance = this;

// 1. Komponenty
playerStatsType = getEntityStoreRegistry().registerComponent(
PlayerStats.class, PlayerStats::new
);
customDataType = getEntityStoreRegistry().registerComponent(
CustomData.class, CustomData::new
);

// 2. Systémy
getEntityStoreRegistry().registerSystem(new StatsUpdateSystem());
getEntityStoreRegistry().registerSystem(new DeathHandlerSystem());

// 3. Příkazy
getCommandRegistry().registerCommand(new StatsCommand());
getCommandRegistry().registerCommand(new AdminStatsCommand());

// 4. Eventy
EventRegistry events = getEventRegistry();

events.registerGlobal(PlayerReadyEvent.class, this::onPlayerReady);
events.register(PlayerDisconnectEvent.class, this::onPlayerDisconnect);
events.registerGlobal(AllWorldsLoadedEvent.class, e -> loadGlobalData());
events.registerGlobal(AddWorldEvent.class, e -> initializeWorld(e.getWorld()));

getLogger().atInfo().log("ExamplePlugin setup complete");
}

@Override
protected void start() {
getLogger().atInfo().log("ExamplePlugin started!");

// Verifikace
ExampleConfig cfg = config.get();
if (cfg == null) {
getLogger().atWarning().log("Config not loaded, using defaults");
} else {
getLogger().atInfo().log("Config loaded: debug=%s", cfg.isDebug());
}

getLogger().atInfo().log("Loaded %d cached players", playerCache.size());
}

@Override
protected void shutdown() {
getLogger().atInfo().log("ExamplePlugin shutting down...");

// Synchronní uložení
try {
saveAllPlayerData();
getLogger().atInfo().log("Saved %d players", playerCache.size());
} catch (Exception e) {
getLogger().at(Level.SEVERE).withCause(e).log("Failed to save player data:");
}

// Cleanup
playerCache.clear();

getLogger().atInfo().log("ExamplePlugin shutdown complete");
}

// Event handlers
private void onPlayerReady(PlayerReadyEvent event) {
Player player = event.getPlayer();
loadPlayerData(player.getUuid());
}

private void onPlayerDisconnect(PlayerDisconnectEvent event) {
Player player = event.getPlayer();
savePlayerData(player.getUuid());
}

// Data methods
private void loadGlobalData() {
getLogger().atInfo().log("Loading global data...");
}

private void initializeWorld(World world) {
getLogger().atInfo().log("Initializing world: %s", world.getName());
}

private void loadPlayerData(UUID uuid) {
// Async load
}

private void savePlayerData(UUID uuid) {
// Async save
}

private void saveAllPlayerData() {
// Sync save all
}

// Gettery
public ComponentType getPlayerStatsType() {
return playerStatsType;
}

public ExampleConfig getPluginConfig() {
return config.get();
}
}

---

Shrnutí

| Registry | Metoda | Účel |
|----------|--------|------|
| getCommandRegistry() | registerCommand(cmd) | Příkazy |
| getEventRegistry() | registerGlobal(event, handler) | Eventy |
| getEntityStoreRegistry() | registerComponent(class, factory) | Entity komponenty |
| getEntityStoreRegistry() | registerSystem(system) | ECS systémy |
| getChunkStoreRegistry() | registerComponent(class, factory) | Chunk komponenty |
| getTaskRegistry() | registerTask(name, runnable, interval) | Periodické úlohy |
| getAssetRegistry() | registerAssetMap(class, map) | Assety |

| Utilita | Metoda | Popis |
|---------|--------|-------|
| Logger | getLogger() | Logování |
| Data folder | getDataDirectory() | Cesta k datům |
| Config | withConfig(codec) | Konfigurace |
| Manifest | getManifest() | Plugin manifest |
| Identifier | getIdentifier() | Plugin ID |

Last updated: 20. ledna 2026