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 |