### Quick Start Hytale Server Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/servers/setup/installation.md A minimal setup to get the Hytale server running. This includes creating a directory, downloading server files, and starting the server with essential arguments. ```bash # Create directory mkdir hytale-server cd hytale-server # Download server files curl -L -o HytaleServer.jar https://cdn.hytale.com/HytaleServer.jar curl -L -o Assets.zip https://cdn.hytale.com/Assets.zip # Start server (minimal) java -Xms4G -Xmx4G -jar HytaleServer.jar --assets Assets.zip -b 0.0.0.0:5520 ``` -------------------------------- ### Listening for Plugin Setup Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/es/modding/plugins/events/server/plugin-setup-event.md Example of how to listen for all plugin setup events globally. ```APIDOC ## Listening for Plugin Setup ### Description This example demonstrates how to register a listener for all `PluginSetupEvent` occurrences globally. This allows you to react to any plugin being set up during server initialization. ### Usage ```java import com.hypixel.hytale.server.core.plugin.event.PluginSetupEvent; import com.hypixel.hytale.event.EventBus; public class PluginManagerPlugin extends PluginBase { @Override public void onEnable(EventBus eventBus) { // Listen for all plugin setup events (global registration) eventBus.registerGlobal(PluginSetupEvent.class, this::onPluginSetup); } private void onPluginSetup(PluginSetupEvent event) { PluginBase plugin = event.getPlugin(); getLogger().info("Plugin being set up: " + plugin.getClass().getName()); } } ``` ``` -------------------------------- ### Install Dependencies and Start Development Server Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/community/contributing.md Clone the repository, install project dependencies, and start the local development server to preview changes. The site will be available at http://localhost:3000. ```bash git clone https://github.com/hytale-community/hytale-wiki.git cd hytale-wiki npm install npm start ``` -------------------------------- ### Listening for Specific Plugin Setup Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/es/modding/plugins/events/server/plugin-setup-event.md Example of how to listen for the setup event of a specific plugin. ```APIDOC ## Listening for Specific Plugin Setup ### Description This example shows how to listen for the `PluginSetupEvent` of a particular plugin by specifying its class as the key. This is useful for plugins that have specific dependencies or require another plugin to be ready before they can proceed. ### Usage ```java import com.hypixel.hytale.server.core.plugin.event.PluginSetupEvent; import com.hypixel.hytale.event.EventBus; public class MyDependentPlugin extends PluginBase { @Override public void onEnable(EventBus eventBus) { // Listen for a specific plugin's setup event using the key eventBus.register( PluginSetupEvent.class, MyDependencyPlugin.class, // Key: the specific plugin class this::onDependencySetup ); } private void onDependencySetup(PluginSetupEvent event) { // This only fires when MyDependencyPlugin is being set up MyDependencyPlugin dependency = (MyDependencyPlugin) event.getPlugin(); getLogger().info("Dependency plugin is ready: " + dependency.getName()); } } ``` ``` -------------------------------- ### Listening for Specific Plugin Setup Event Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/server/plugin-setup-event.md Example of registering a listener for a specific plugin's setup event using its class as the key. This is useful for managing plugin dependencies. ```java import com.hypixel.hytale.server.core.plugin.event.PluginSetupEvent; import com.hypixel.hytale.event.EventBus; public class MyDependentPlugin extends PluginBase { @Override public void onEnable(EventBus eventBus) { // Listen for a specific plugin's setup event using the key eventBus.register( PluginSetupEvent.class, MyDependencyPlugin.class, // Key: the specific plugin class this::onDependencySetup ); } private void onDependencySetup(PluginSetupEvent event) { // This only fires when MyDependencyPlugin is being set up MyDependencyPlugin dependency = (MyDependencyPlugin) event.getPlugin(); getLogger().info("Dependency plugin is ready: " + dependency.getName()); } } ``` -------------------------------- ### Registering Events and Systems in setup() Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/plugin-lifecycle.md A simpler example of registering an event listener for asset loading and a chunk physics system within the `setup()` method of a JavaPlugin. The event listener is a static method. ```java public class BlockPhysicsPlugin extends JavaPlugin { public BlockPhysicsPlugin(@Nonnull JavaPluginInit init) { super(init); } @Override protected void setup() { // Validate prefabs when assets are loaded getEventRegistry().register(LoadAssetEvent.class, BlockPhysicsPlugin::validatePrefabs); // Register chunk physics system getChunkStoreRegistry().registerSystem(new BlockPhysicsSystems.Ticking()); } private static void validatePrefabs(LoadAssetEvent event) { // Validation logic... } } ``` -------------------------------- ### Plugin Start Method Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/plugin-lifecycle.md The `start()` method is called after all plugins have finished their `setup()`. It's the safe place for cross-plugin communication and starting scheduled tasks. ```java protected void start() { // Safe to interact with other plugins here OtherPlugin other = OtherPlugin.getInstance(); if (other != null) { other.registerIntegration(this); } // Start any scheduled tasks getTaskRegistry().scheduleRepeating(this::tick, 20, 20); // Every second getLogger().info("Plugin started and ready!"); } ``` -------------------------------- ### Start Hytale Server on PC Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/servers/budget-hosting.md Use this command to start the Hytale server on your local machine. Ensure Java 25 is installed and the server JAR file is in the current directory. ```bash java -Xms4G -Xmx4G -jar hytale-server.jar ``` -------------------------------- ### Listening for All Plugin Setup Events Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/server/plugin-setup-event.md Example of how to register a global listener for PluginSetupEvent to react to any plugin being set up. This is useful for tracking all loaded plugins. ```java import com.hypixel.hytale.server.core.plugin.event.PluginSetupEvent; import com.hypixel.hytale.event.EventBus; public class PluginManagerPlugin extends PluginBase { @Override public void onEnable(EventBus eventBus) { // Listen for all plugin setup events (global registration) eventBus.registerGlobal(PluginSetupEvent.class, this::onPluginSetup); } private void onPluginSetup(PluginSetupEvent event) { PluginBase plugin = event.getPlugin(); getLogger().info("Plugin being set up: " + plugin.getClass().getName()); } } ``` -------------------------------- ### Clone and Run HytaleDocs Locally Source: https://github.com/timiliris/hytale-docs/blob/master/README.md Follow these steps to clone the repository, install dependencies, and start the development server for HytaleDocs. ```bash git clone https://github.com/timiliris/Hytale-Docs.git cd Hytale-Docs npm install npm run dev ``` -------------------------------- ### PHP SDK Usage Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/sdks/php.md This example demonstrates how to initialize the PHP SDK client and fetch blog posts. ```APIDOC ## PHP SDK Usage ### Description This example demonstrates how to initialize the PHP SDK client and fetch blog posts. ### Method ```php $client->blog()->getPosts() ``` ### Parameters This method does not take any parameters. ### Request Example ```php use HytaleAPI\Client; $client = new Client(); $posts = $client->blog()->getPosts(); ``` ### Response #### Success Response Returns a list of blog posts. #### Response Example ```json [ { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Example Post", "content": "This is the content of the example post.", "author": "Example Author", "createdAt": "2023-10-27T10:00:00Z" } ] ``` ``` -------------------------------- ### Prefab Spawner Set Command Examples Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/modules/prefab-system.md Examples demonstrating how to use the `/prefabspawner set` command with different options. ```bash /prefabspawner set buildings.houses.small_house /prefabspawner set trees.oak fitHeightmap=true /prefabspawner set dungeons.entrance defaultWeight=0.5 ``` -------------------------------- ### PlayerSettings Usage Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/ecs.md Demonstrates how to get default player settings and create custom settings, then add them to a player entity. PickupLocation determines item placement. ```java // Get default settings PlayerSettings settings = PlayerSettings.defaults(); // Create custom settings PlayerSettings customSettings = new PlayerSettings( true, // showEntityMarkers PickupLocation.Inventory, // armor -> inventory PickupLocation.Hotbar, // weapons -> hotbar PickupLocation.Inventory, // usables -> inventory PickupLocation.Inventory, // blocks -> inventory PickupLocation.Inventory, // misc -> inventory new PlayerCreativeSettings(true, false) // creative settings ); commandBuffer.addComponent(playerRef, PlayerSettings.getComponentType(), customSettings); ``` -------------------------------- ### Plugin Example for Entity UI Components Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/modules/entity-ui.md Demonstrates how to listen for player additions to a world and access their UI components. Includes methods for getting UI components by ID and checking for their existence on an entity. ```java public class EntityUIPlugin extends JavaPlugin { public EntityUIPlugin(@Nonnull JavaPluginInit init) { super(init); } @Override protected void setup() { // Listen for when players are added to a world getEventRegistry().register(AddPlayerToWorldEvent.class, this::onPlayerAddedToWorld); } private void onPlayerAddedToWorld(AddPlayerToWorldEvent event) { World world = event.getWorld(); Store store = world.getEntityStore().getStore(); Ref entityRef = event.getHolder(); // Get the entity's UI component list UIComponentList uiList = store.getComponent(entityRef, UIComponentList.getComponentType()); if (uiList != null) { // Get current component IDs int[] componentIds = uiList.getComponentIds(); getLogger().info("Player added to world with " + componentIds.length + " UI components"); } } // Get UI component by ID public EntityUIComponent getUIComponent(String componentId) { IndexedLookupTableAssetMap assetMap = EntityUIComponent.getAssetMap(); int index = assetMap.getIndex(componentId); return assetMap.get(index); } // Check if an entity has a specific UI component public boolean hasUIComponent(Store store, Ref entityRef, String componentId) { UIComponentList uiList = store.getComponent(entityRef, UIComponentList.getComponentType()); if (uiList == null) { return false; } IndexedLookupTableAssetMap assetMap = EntityUIComponent.getAssetMap(); int targetIndex = assetMap.getIndex(componentId); for (int id : uiList.getComponentIds()) { if (id == targetIndex) { return true; } } return false; } } ``` -------------------------------- ### Usage Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/es/modding/plugins/events/npc/loaded-npc-event.md An example demonstrating how to register a listener for the LoadedNPCEvent to track and process NPC loading. ```APIDOC ## Usage Example ```java import com.hypixel.hytale.server.spawning.LoadedNPCEvent; import com.hypixel.hytale.server.npc.asset.builder.BuilderInfo; import com.hypixel.hytale.event.EventBus; import com.hypixel.hytale.event.EventPriority; public class NPCLoadTrackerPlugin extends PluginBase { private final Set trackedNPCs = new HashSet<>(); @Override public void onEnable() { EventBus.register(LoadedNPCEvent.class, this::onNPCLoaded, EventPriority.NORMAL); } private void onNPCLoaded(LoadedNPCEvent event) { BuilderInfo builderInfo = event.getBuilderInfo(); // Log each NPC as it loads getLogger().info("NPC loaded: " + builderInfo.toString()); // Track specific NPC types String npcIdentifier = builderInfo.getIdentifier(); trackedNPCs.add(npcIdentifier); // Perform per-NPC initialization initializeNPCExtensions(builderInfo); } private void initializeNPCExtensions(BuilderInfo builderInfo) { // Add custom behavior or data to the NPC definition // This runs before the NPC can be spawned in the world } public Set getTrackedNPCs() { return Collections.unmodifiableSet(trackedNPCs); } } ``` ``` -------------------------------- ### Install PHP SDK Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/sdks/php.md Use Composer to install the Hytale API SDK for PHP. ```bash composer require hytale-api/sdk-php ``` -------------------------------- ### Plugin Lifecycle Methods Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/overview.md Implement these methods to manage your plugin's behavior during different stages of the server's operation. Use `setup()` for registration, `start()` for inter-plugin communication, and `shutdown()` for cleanup. ```java protected void setup() { // Called first - register everything here getCommandRegistry().registerCommand(new MyCommand()); getEventRegistry().register(PlayerJoinEvent.class, this::onJoin); } ``` ```java protected void start() { // Called after ALL plugins have completed setup() // Safe to interact with other plugins here } ``` ```java protected void shutdown() { // Called when server stops - clean up here savePlayerData(); } ``` -------------------------------- ### Register Player Setup Connect Event Handler Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/player/player-setup-connect-event.md Register a handler to process the PlayerSetupConnectEvent. This example demonstrates ban checking, server capacity management, whitelist enforcement, and logging connection attempts. ```java eventBus.register(PlayerSetupConnectEvent.class, event -> { String username = event.getUsername(); UUID uuid = event.getUuid(); // Check if player is banned if (isBanned(uuid)) { event.setCancelled(true); event.setReason("You are banned from this server!"); return; } // Check server capacity if (getOnlinePlayerCount() >= getMaxPlayers()) { if (!isVIP(uuid)) { event.setCancelled(true); event.setReason("Server is full! VIP members can still join."); return; } } // Check whitelist if (isWhitelistEnabled() && !isWhitelisted(uuid)) { event.setCancelled(true); event.setReason("You are not whitelisted on this server."); return; } logger.info("Player " + username + " is connecting..."); }); ``` -------------------------------- ### Example Server Log Output Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/es/modding/plugins/events/player/player-setup-disconnect-event.md This is an example of the server console output when the `PlayerSetupDisconnectEvent` is fired and logged by a test listener. ```log [INFO] [TestLogger] [DocTest] Player Event: PlayerSetupDisconnectEvent | Player: Username [INFO] [EventTracker] [DocTest] Event fired: PlayerSetupDisconnectEvent ``` -------------------------------- ### Install JavaScript SDK Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/sdks/javascript.md Use npm to install the Hytale API JavaScript SDK. ```bash npm install @hytale-api/sdk ``` -------------------------------- ### Usage Examples Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/player/player-mouse-motion-event.md Examples demonstrating how to register listeners for PlayerMouseMotionEvent to handle player mouse movements and interactions. ```APIDOC ## Usage Example ```java // Register a handler for mouse motion events eventBus.register(PlayerMouseMotionEvent.class, event -> { Player player = event.getPlayer(); Vector2f screenPos = event.getScreenPoint(); // Track mouse position for UI updatePlayerCursorPosition(player, screenPos); // Highlight block under cursor Vector3i targetBlock = event.getTargetBlock(); if (targetBlock != null) { highlightBlock(player, targetBlock); } // Show entity tooltip when hovering Entity targetEntity = event.getTargetEntity(); if (targetEntity != null) { showEntityTooltip(player, targetEntity); } }); // Implement hover effects eventBus.register(PlayerMouseMotionEvent.class, event -> { Entity hoveredEntity = event.getTargetEntity(); Player player = event.getPlayer(); // Clear previous hover state clearHoverState(player); if (hoveredEntity != null) { // Apply hover outline effect applyHoverOutline(player, hoveredEntity); // Show interaction prompt if (hoveredEntity instanceof NPC) { showInteractionPrompt(player, "Press E to talk"); } } }); // Block selection preview system eventBus.register(PlayerMouseMotionEvent.class, event -> { Item item = event.getItemInHand(); Vector3i targetBlock = event.getTargetBlock(); if (item != null && item.getType().equals("custom:building_tool") && targetBlock != null) { // Show placement preview showPlacementPreview(event.getPlayer(), targetBlock, item); } }); ``` ``` -------------------------------- ### SettingsPage Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/custom-ui.md Example implementation of a custom settings page, demonstrating how to bind UI events and handle data. ```APIDOC ## Class: SettingsPage ### Description An example implementation of `InteractiveCustomUIPage` for a settings screen. ### Fields - `LAYOUT`: String representing the UI layout file path (`"YourPlugin/SettingsPage.ui"`). ### Constructor - `SettingsPage(PlayerRef playerRef)` - Initializes the page with the player reference, `CanDismiss` lifetime, and `SettingsEventData.CODEC`. ### Methods - `build(...)` - Binds the "SaveButton" and "CloseButton" to trigger "save" and "close" actions respectively. - `handleDataEvent(..., SettingsEventData data)` - Handles the "close" action by calling `this.close()`. - Handles the "save" action by sending a success notification to the player. ### Inner Class: SettingsEventData - `CODEC`: A `BuilderCodec` for the `SettingsEventData` class, which includes an `action` field of type String. ``` -------------------------------- ### PlayerSkinComponent Usage Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/ecs.md Example demonstrating how to get and use the PlayerSkinComponent in code. ```APIDOC ## PlayerSkinComponent Usage Example ### Description Illustrates common use cases for the `PlayerSkinComponent`, such as retrieving player skin data and triggering network updates. ### Code Example ```java // Get player skin component PlayerSkinComponent skinComp = store.getComponent(playerRef, PlayerSkinComponent.getComponentType()); // Get player skin data PlayerSkin skin = skinComp.getPlayerSkin(); // Force skin update to clients skinComp.setNetworkOutdated(); // Check if skin needs synchronization if (skinComp.consumeNetworkOutdated()) { // Send skin data to clients } ``` ``` -------------------------------- ### Initialize and Use SDK Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/sdks/javascript.md Demonstrates how to install the SDK using npm and then import and initialize the HytaleAPI class to fetch blog posts. ```APIDOC ## Installation ```bash npm install @hytale-api/sdk ``` ## Usage ```javascript import { HytaleAPI } from '@hytale-api/sdk'; const api = new HytaleAPI(); const posts = await api.blog.getPosts(); ``` ``` -------------------------------- ### Registering Codecs, Events, and Systems in setup() Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/plugin-lifecycle.md Demonstrates registering codec types, a global event listener with early priority, and chunk systems within the `setup()` method of a JavaPlugin. It also shows how to set a block tick provider. ```java public class BlockTickPlugin extends JavaPlugin implements IBlockTickProvider { private static BlockTickPlugin instance; public BlockTickPlugin(@Nonnull JavaPluginInit init) { super(init); instance = this; } @Override protected void setup() { // Register codec types TickProcedure.CODEC.register("BasicChance", BasicChanceBlockGrowthProcedure.class, BasicChanceBlockGrowthProcedure.CODEC); TickProcedure.CODEC.register("SplitChance", SplitChanceBlockGrowthProcedure.class, SplitChanceBlockGrowthProcedure.CODEC); // Register global event listener with early priority getEventRegistry().registerGlobal(EventPriority.EARLY, ChunkPreLoadProcessEvent.class, this::discoverTickingBlocks); // Register chunk systems ChunkStore.REGISTRY.registerSystem(new ChunkBlockTickSystem.PreTick()); ChunkStore.REGISTRY.registerSystem(new ChunkBlockTickSystem.Ticking()); ChunkStore.REGISTRY.registerSystem(new MergeWaitingBlocksSystem()); // Set provider BlockTickManager.setBlockTickProvider(this); } } ``` -------------------------------- ### Install Blockbench using Winget Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/getting-started/environment-setup.md Installs Blockbench using the Windows Package Manager (winget). This is a quick way to get the tool if you are on Windows. ```bash # Download from blockbench.net or use package manager winget install JannisX11.Blockbench ``` -------------------------------- ### Complete Plugin Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/plugin-lifecycle.md A comprehensive example demonstrating all plugin lifecycle methods and common patterns, including configuration, event handling, and command registration. ```java package com.example.myplugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.Config; import com.hypixel.hytale.server.core.logging.HytaleLogger; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.concurrent.CompletableFuture; public class MyPlugin extends JavaPlugin { private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); private static MyPlugin instance; private Config config; private PlayerDataManager playerDataManager; // Singleton access for other plugins public static MyPlugin getInstance() { return instance; } public MyPlugin(@Nonnull JavaPluginInit init) { super(init); instance = this; // Register config for async loading config = withConfig(MyConfig.CODEC); } @Override @Nullable public CompletableFuture preLoad() { LOGGER.info("PreLoading configuration..."); // Config files are loaded automatically return super.preLoad(); } @Override protected void setup() { LOGGER.info("Setting up plugin..."); // Initialize managers playerDataManager = new PlayerDataManager(getDataDirectory()); // Register commands getCommandRegistry().registerCommand(new SpawnCommand()); getCommandRegistry().registerCommand(new HomeCommand()); // Register event listeners getEventRegistry().register(PlayerJoinEvent.class, this::onPlayerJoin); getEventRegistry().register(PlayerQuitEvent.class, this::onPlayerQuit); getEventRegistry().register(EventPriority.EARLY, PlayerChatEvent.class, this::onChat); // Register ECS systems getEntityStoreRegistry().registerSystem(new PlayerTrackingSystem()); getChunkStoreRegistry().registerSystem(new CustomBlockSystem()); LOGGER.info("Setup complete!"); } @Override protected void start() { LOGGER.info("Starting plugin..."); // Safe to interact with other plugins now EconomyPlugin economy = EconomyPlugin.getInstance(); if (economy != null) { economy.registerCurrency("tokens", 0); LOGGER.info("Integrated with EconomyPlugin"); } // Start scheduled tasks getTaskRegistry().scheduleRepeating(this::autoSave, 6000, 6000); // Every 5 minutes LOGGER.info("Plugin started! Welcome: " + config.get().getWelcomeMessage()); } @Override protected void shutdown() { LOGGER.info("Shutting down..."); // Save all player data if (playerDataManager != null) { playerDataManager.saveAll(); } // Cleanup instance = null; LOGGER.info("Shutdown complete!"); } // Event handlers private void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); playerDataManager.load(player); player.sendMessage(config.get().getWelcomeMessage()); } private void onPlayerQuit(PlayerQuitEvent event) { playerDataManager.save(event.getPlayer()); } private void onChat(PlayerChatEvent event) { // Early priority - can modify or cancel if (event.getMessage().contains("badword")) { event.setCancelled(true); } } private void autoSave() { playerDataManager.saveAll(); LOGGER.debug("Auto-save complete"); } // Public API for other plugins public MyConfig getConfiguration() { return config.get(); } } ``` -------------------------------- ### Role JSON Configuration Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/modules/npc-system.md Example of a Role definition in JSON format, specifying ID, model, NPC groups, start state, entity slots, motion controllers, and states with instructions. ```json { "Id": "Example_NPC", "Model": "npc/example_npc", "NPCGroups": ["Friendly", "Villager"], "StartState": "Idle", "StartSubState": "Default", "EntitySlots": { "Target": { "UpdateRate": 0.5, "Range": 20.0, "MaxCount": 1 } }, "MotionControllers": { "Walk": { "MaxSpeed": 4.0, "Acceleration": 20.0, "TurnSpeed": 180.0 } }, "States": { "Idle": { "SubStates": { "Default": { "Instructions": [ { "Sensors": ["SensorPlayerNearby"], "Actions": ["ActionGreet"], "BodyMotion": "BodyMotionIdle" } ] } } } } } ``` -------------------------------- ### Build and Test UI Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/custom-ui.md Build the project and copy the JAR to the server's plugins folder. Restart the server and use the /myui command to test. ```bash ./gradlew build ``` -------------------------------- ### Plugin Setup Method Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/plugin-lifecycle.md The `setup()` method is used for registering plugin functionality like commands, event listeners, ECS systems, and assets. Avoid heavy work or cross-plugin interactions here. ```java protected void setup() { // Register commands getCommandRegistry().registerCommand(new MyCommand()); // Register event listeners getEventRegistry().register(PlayerJoinEvent.class, this::onPlayerJoin); // Register ECS systems getEntityStoreRegistry().registerSystem(new MyEntitySystem()); getChunkStoreRegistry().registerSystem(new MyChunkSystem()); // Register assets getAssetRegistry().register(MyAsset.class, MyAsset.CODEC); // Log completion getLogger().info("Setup complete!"); } ``` -------------------------------- ### Instruction JSON Configuration Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/modules/npc-system.md Example JSON for configuring an instruction, specifying sensors (player proximity, timer finished), actions (state change, start timer), and head motion (watch target). ```json { "Instructions": [ { "Sensors": { "Type": "And", "Sensors": [ {"Type": "Player", "Range": 10.0, "Slot": "Target"}, {"Type": "Timer", "Name": "GreetCooldown", "Condition": "Finished"} ] }, "Actions": [ {"Type": "State", "State": "Greeting", "SubState": "Default"}, {"Type": "TimerStart", "Name": "GreetCooldown", "Duration": 30.0} ], "BodyMotion": {"Type": "Nothing"}, "HeadMotion": {"Type": "Watch", "Slot": "Target"} } ] } ``` -------------------------------- ### Usage Examples Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/ecs.md Demonstrates how to obtain default player settings and create custom player settings. ```APIDOC ## Usage Examples ### Getting Default Settings ```java PlayerSettings settings = PlayerSettings.defaults(); ``` ### Creating Custom Settings ```java PlayerSettings customSettings = new PlayerSettings( true, // showEntityMarkers PickupLocation.Inventory, // armorItemsPreferredPickupLocation PickupLocation.Hotbar, // weaponAndToolItemsPreferredPickupLocation PickupLocation.Inventory, // usableItemsItemsPreferredPickupLocation PickupLocation.Inventory, // solidBlockItemsPreferredPickupLocation PickupLocation.Inventory, // miscItemsPreferredPickupLocation new PlayerCreativeSettings(true, false) // creativeSettings ); // To add these settings to a player entity: // commandBuffer.addComponent(playerRef, PlayerSettings.getComponentType(), customSettings); ``` ``` -------------------------------- ### Plugin Lifecycle Methods Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/plugins.md Override these methods to handle plugin lifecycle events such as setup, start, and shutdown. ```APIDOC ## Plugin Lifecycle Methods Override these methods to handle lifecycle events: ```java public class MyPlugin extends JavaPlugin { public MyPlugin(@Nonnull JavaPluginInit init) { super(init); } /** * Called during the setup phase. Use this method to register commands, events, and initialise resources. * Dependencies are guaranteed to be in the SETUP state or later. */ @Override protected void setup() { // Register commands getCommandRegistry().registerCommand(new MyCommand()); // Register event handlers getEventRegistry().register(PlayerJoinEvent.class, this::onPlayerJoin); // Register tasks getTaskRegistry().registerTask(myAsyncTask()); } /** * Called during the start phase. Dependencies are guaranteed to be in the ENABLED state. * Asset packs should be registered here. */ @Override protected void start() { getLogger().info("Plugin started successfully!"); } /** * Called when the plugin is shutting down. Use this method to clean up resources, save data, and perform other teardown operations. */ @Override protected void shutdown() { getLogger().info("Cleaning up resources..."); } } ``` ``` -------------------------------- ### Install Hytale Server on Oracle Cloud VM Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/servers/budget-hosting.md Connect to your Oracle Cloud VM via SSH, update the system, install Java 25, create a server directory, and then download and start the Hytale server JAR. ```bash ssh -i your-key.pem ubuntu@your-instance-ip sudo apt update && sudo apt upgrade -y sudo apt install -y openjdk-25-jdk mkdir -p ~/hytale-server cd ~/hytale-server # Download and start the server # (Download hytale-server.jar from hytale.com) java -Xms4G -Xmx4G -jar hytale-server.jar ``` -------------------------------- ### Server Ready Announcement Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/world/all-worlds-loaded-event.md This snippet demonstrates how to announce server readiness and enable player connections after all worlds have loaded. It also shows how to notify external systems. ```java eventBus.register(EventPriority.LAST, AllWorldsLoadedEvent.class, event -> { // Announce server is ready logger.info("Server initialization complete - all worlds loaded"); // Enable the server listener for player connections server.setAcceptingConnections(true); // Notify external systems (Discord bots, monitoring, etc.) notifyExternalSystems("Server is ready"); }); ``` -------------------------------- ### Get Player Username Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/es/modding/plugins/events/player/player-setup-connect-event.md Retrieves the username of the player attempting to connect. This is part of the player's connection setup information. ```java public String getUsername() ``` -------------------------------- ### Download and Run Hytale Server with Docker Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/servers/hosting/docker.md Commands to set up directories, download server files using the Hytale Downloader CLI, and start the Docker container. Remember to extract `HytaleServer.jar` and `Assets.zip`. ```bash # Create directories mkdir -p data/{worlds,config,mods,plugins} server-files # Download server files using Hytale Downloader CLI (recommended) wget https://downloader.hytale.com/hytale-downloader.zip unzip hytale-downloader.zip ./hytale-downloader-linux-amd64 # Extract the Server folder and Assets.zip to server-files/ # Or copy from your Hytale launcher installation: # Windows: %appdata%\Hytale\install\release\package\game\latest # Linux: $XDG_DATA_HOME/Hytale/install/release/package/game/latest # macOS: ~/Application Support/Hytale/install/release/package/game/latest # Start container docker-compose up -d # View logs docker-compose logs -f ``` -------------------------------- ### Getting Disconnect Reason Details Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/player/player-disconnect-event.md Practical example demonstrating how to use `getDisconnectReason()` to determine the cause of a player's disconnection. ```APIDOC ### Practical Examples #### Getting Disconnect Reason Details The `getDisconnectReason()` method returns a `PacketHandler.DisconnectReason` object that contains either a server-side reason or a client-side disconnect type: ```java eventBus.register(PlayerDisconnectEvent.class, event -> { PlayerRef player = event.getPlayerRef(); PacketHandler.DisconnectReason reason = event.getDisconnectReason(); // Check if it was a server-initiated disconnect String serverReason = reason.getServerDisconnectReason(); if (serverReason != null) { logger.info("Server kicked " + player.getUsername() + ": " + serverReason); return; } // Check if it was a client-initiated disconnect DisconnectType clientType = reason.getClientDisconnectType(); if (clientType != null) { switch (clientType) { case Disconnect -> logger.info(player.getUsername() + " disconnected normally"); case Crash -> logger.warn(player.getUsername() + " disconnected due to crash"); } } }); ``` ``` -------------------------------- ### Plugin Setup and Registry Access Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/plugins.md Demonstrates how to access various registries within the plugin's setup method to register different server components like commands, events, tasks, and more. ```java public class MyPlugin extends JavaPlugin { @Override protected void setup() { // Command registration CommandRegistry commands = getCommandRegistry(); // Event handling EventRegistry events = getEventRegistry(); // Scheduled tasks TaskRegistry tasks = getTaskRegistry(); // Block state registration BlockStateRegistry blockStates = getBlockStateRegistry(); // Entity registration EntityRegistry entities = getEntityRegistry(); // Client features ClientFeatureRegistry clientFeatures = getClientFeatureRegistry(); // Asset registration AssetRegistry assets = getAssetRegistry(); // Entity store components ComponentRegistryProxy entityStore = getEntityStoreRegistry(); // Chunk store components ComponentRegistryProxy chunkStore = getChunkStoreRegistry(); // Codec registration CodecMapRegistry codecRegistry = getCodecRegistry(someCodecMap); } } ``` -------------------------------- ### Getting Event Type Description Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/events/npc/entity-event-type.md Provides an example of how to retrieve the human-readable description for an EntityEventType, useful for UI elements or logging. ```java // Get description for UI display public String getEventTypeLabel(EntityEventType type) { return type.get(); // Returns "On taking damage", "On dying", etc. } ``` -------------------------------- ### Start Hytale Server Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/servers/overview.md Use this command to start the Hytale server. Adjust memory allocation (-Xms, -Xmx) as needed. Ensure the JAR file and assets are correctly specified. ```bash java -Xms4G -Xmx8G -XX:AOTCache=HytaleServer.aot -jar HytaleServer.jar --assets Assets.zip -b 0.0.0.0:5520 ``` -------------------------------- ### Setup Entity Interactions Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/modules/interactions.md Code to set up interactions on an entity by getting or creating the Interactions component and defining interaction types and hints. ```java public void setupEntityInteractions(Ref entityRef, CommandBuffer commandBuffer) { // Get or create Interactions component Interactions interactions = commandBuffer.getComponent( entityRef, Interactions.getComponentType() ); if (interactions == null) { interactions = new Interactions(); commandBuffer.putComponent(entityRef, Interactions.getComponentType(), interactions); } // Set interaction for "Use" type interactions.setInteractionId(InteractionType.Use, "my_custom_interaction"); // Set interaction hint for UI interactions.setInteractionHint("Press E to interact"); } ``` -------------------------------- ### Getting an Entity's UI Components Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/modules/entity-ui.md Example code demonstrating how to retrieve an entity's UI components using the UIComponentList. ```APIDOC ### Getting an Entity's UI Components ```java // Get the component type ComponentType componentType = UIComponentList.getComponentType(); // Get an entity's UI component list UIComponentList uiList = store.getComponent(entityRef, componentType); // Get the component IDs int[] componentIds = uiList.getComponentIds(); ``` ``` -------------------------------- ### Initialize and Use JavaScript SDK Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/sdks/javascript.md Import the HytaleAPI class and use it to fetch blog posts. Ensure the SDK is installed before use. ```javascript import { HytaleAPI } from '@hytale-api/sdk'; const api = new HytaleAPI(); const posts = await api.blog.getPosts(); ``` -------------------------------- ### Complete Java Plugin Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/plugins.md Demonstrates a full Java plugin with command registration, event handling, and lifecycle methods. Ensure the manifest.json file is correctly configured for the plugin to be recognized. ```java package com.example.greeting; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase; import com.hypixel.hytale.server.core.command.system.CommandContext; import com.hypixel.hytale.server.core.Message; import javax.annotation.Nonnull; public class GreetingPlugin extends JavaPlugin { public GreetingPlugin(@Nonnull JavaPluginInit init) { super(init); } @Override protected void setup() { getLogger().info("Setting up GreetingPlugin..."); // Register the command getCommandRegistry().registerCommand(new GreetCommand()); // Register the event handler getEventRegistry().register(PlayerJoinEvent.class, event -> { event.getPlayer().sendMessage( Message.raw("Welcome to the server!") ); }); } @Override protected void start() { getLogger().info("GreetingPlugin started!"); } @Override protected void shutdown() { getLogger().info("GreetingPlugin shutting down..."); } private class GreetCommand extends CommandBase { public GreetCommand() { super("greet", "greeting.command.desc"); } @Override protected void executeSync(@Nonnull CommandContext context) { context.sendMessage(Message.raw("Hello from GreetingPlugin!")); } } } ``` ```json { "Group": "Example", "Name": "GreetingPlugin", "Version": "1.0.0", "Description": "A simple greeting plugin", "Main": "com.example.greeting.GreetingPlugin", "Authors": [ { "Name": "Example Developer" } ] } ``` -------------------------------- ### Plugin Loading Process Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/modding/plugins/plugin-lifecycle.md Overview of the plugin loading process, detailing the phases from discovery and dependency validation to instantiation, pre-load, setup, and start. ```APIDOC ## Loading Process The plugin loading process follows these phases: 1. **Discovery** - Plugins are discovered from: - Core plugins (built-in) - Builtin directory - Classpath (`manifest.json`/`manifests.json`) - The `mods` directory 2. **Dependency Validation** - Dependencies are validated against loaded plugins and server version requirements 3. **Load Order Calculation** - Plugins are sorted based on: - `dependencies` in manifest - `LoadBefore` declarations 4. **Instantiation** - Constructor is invoked with `JavaPluginInit` 5. **PreLoad** - `preLoad()` is called to load configs asynchronously 6. **Setup** - `setup()` is called to register functionality 7. **Start** - `start()` is called after all plugins are set up ``` -------------------------------- ### Initialize and Use PHP SDK Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/sdks/php.md Instantiate the Hytale API client and fetch blog posts. ```php use HytaleAPI\Client; $client = new Client(); $posts = $client->blog()->getPosts(); ``` -------------------------------- ### Basic Plugin Structure Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/plugins.md Extend the JavaPlugin class to create a new plugin. Implement setup, start, and shutdown methods for lifecycle management. ```java package com.example.myplugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import javax.annotation.Nonnull; public class MyPlugin extends JavaPlugin { public MyPlugin(@Nonnull JavaPluginInit init) { super(init); } @Override protected void setup() { // Called during the plugin setup phase getLogger().info("MyPlugin is setting up!"); } @Override protected void start() { // Called when the plugin starts getLogger().info("MyPlugin has started!"); } @Override protected void shutdown() { // Called when the plugin is being disabled getLogger().info("MyPlugin is shutting down!"); } } ``` -------------------------------- ### Usage Example: Setting up NPC Block Events Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/es/modding/plugins/events/npc/block-event-view.md Shows how to obtain a BlockEventView from the Blackboard and initialize an NPC's block event listeners. ```java // The BlockEventView is typically managed by the Blackboard system Blackboard blackboard = componentAccessor.getResource(Blackboard.getResourceType()); BlockEventView blockView = blackboard.getView(BlockEventView.class, ref, componentAccessor); // Initialize an NPC's block event listeners public void setupNpcBlockEvents(Ref ref, NPCEntity npc, BlockEventView view) { view.initialiseEntity(ref, npc); } ``` -------------------------------- ### UI DSL File Structure Example Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/ui-reference.md Demonstrates the basic structure of a .ui file, including comments, imports, custom styles, and the root element definition. Ensure only one root element is present per file. ```ui // Comments start with // // Import external UI files $C = "../Common.ui"; $Other = "path/to/Other.ui"; // Define custom styles/constants @MyConstant = 100; @MyStyle = LabelStyle(FontSize: 16, TextColor: #ffffff); // Root element (only ONE root element per file) Group { // Properties use colon and end with semicolon PropertyName: value; // Child elements ChildElement { // ... } } ``` -------------------------------- ### Get All Passengers Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/ecs.md Retrieves the list of all entities currently riding a given entity by calling `getPassengers()` on the `MountedByComponent`. The example iterates through the list to process each rider. ```java // Get all passengers List> passengers = mountedBy.getPassengers(); for (Ref passenger : passengers) { // Process each rider } ``` -------------------------------- ### Start Hytale Server on Windows Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/servers/setup/installation.md Use this batch script to launch the Hytale server on Windows. Ensure Java 25 is installed and HytaleServer.jar is in the same directory as Assets.zip. ```batch @echo off java -Xms8G -Xmx8G \ -XX:+UseG1GC \ -XX:+ParallelRefProcEnabled \ -XX:MaxGCPauseMillis=200 \ -XX:+DisableExplicitGC \ -XX:+AlwaysPreTouch \ -XX:+UseCompactObjectHeaders \ -Djava.net.preferIPv4Stack=true \ -jar HytaleServer.jar \ --assets Assets.zip \ -b 0.0.0.0:5520 \ --auth-mode authenticated \ --allow-op pause ``` -------------------------------- ### Plugin Lifecycle Methods Source: https://github.com/timiliris/hytale-docs/blob/master/content/docs/en/api/server-internals/plugins.md Override these methods to handle plugin lifecycle events such as setup, start, and shutdown. Dependencies are guaranteed to be in specific states when these methods are called. ```java public class MyPlugin extends JavaPlugin { public MyPlugin(@Nonnull JavaPluginInit init) { super(init); } /** * Called during the setup phase. * Use this method to register commands, events, and initialise resources. * Dependencies are guaranteed to be in the SETUP state or later. */ @Override protected void setup() { // Register commands getCommandRegistry().registerCommand(new MyCommand()); // Register event handlers getEventRegistry().register(PlayerJoinEvent.class, this::onPlayerJoin); // Register tasks getTaskRegistry().registerTask(myAsyncTask()); } /** * Called during the start phase. * Dependencies are guaranteed to be in the ENABLED state. * Asset packs should be registered here. */ @Override protected void start() { getLogger().info("Plugin started successfully!"); } /** * Called when the plugin is shutting down. * Use this method to clean up resources, save data, and perform other teardown operations. */ @Override protected void shutdown() { getLogger().info("Cleaning up resources..."); } } ```