--- title: Codecs type: docs weight: 3 --- Codecs in Hytale provide a powerful way to serialize and deserialize data. They're used for configuration files, network communication, and data persistence. **Package:** `com.hypixel.hytale.codec` ## BuilderCodec The `BuilderCodec` is the primary codec type for complex objects. It uses a builder pattern for construction. ### Defining a Codec ```java import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; public class MyConfig { private String serverName; private int maxPlayers = 20; // Default value private boolean debugMode = false; public static final BuilderCodec CODEC = BuilderCodec.builder(MyConfig.class, MyConfig::new) .append(new KeyedCodec<>("ServerName", Codec.STRING), (config, val) -> config.serverName = val, config -> config.serverName) .add() .append(new KeyedCodec<>("MaxPlayers", Codec.INTEGER), (config, val) -> config.maxPlayers = val, config -> config.maxPlayers) .add() .append(new KeyedCodec<>("DebugMode", Codec.BOOLEAN), (config, val) -> config.debugMode = val, config -> config.debugMode) .add() .build(); // Getters... public String getServerName() { return serverName; } public int getMaxPlayers() { return maxPlayers; } public boolean isDebugMode() { return debugMode; } } ``` {{< callout type="warning" >}} **KeyedCodec keys must start with an uppercase letter** (PascalCase). Keys like `"serverName"` will throw an `IllegalArgumentException`. {{< /callout >}} ### JSON Structure The codec above corresponds to this JSON: ```json { "ServerName": "My Server", "MaxPlayers": 100, "DebugMode": true } ``` ## Basic Codecs Hytale provides codecs for primitive types: | Codec | Type | |-------|------| | `Codec.STRING` | String | | `Codec.INTEGER` | Integer | | `Codec.LONG` | Long | | `Codec.FLOAT` | Float | | `Codec.DOUBLE` | Double | | `Codec.BOOLEAN` | Boolean | | `Codec.BYTE` | Byte | | `Codec.SHORT` | Short | ## Using Config Files Register configuration files in `setup()`: ```java import com.hypixel.hytale.server.core.util.Config; import java.util.logging.Level; private Config config; @Override public void setup() { config = withConfig(MyConfig.CODEC); } @Override public void start() { MyConfig cfg = config.get(); getLogger().at(Level.INFO).log("Server name: " + cfg.getServerName()); } ``` ### Config File Location Config files are automatically stored in your plugin's data directory: ``` Plugins/ └── your-plugin/ └── config.json ``` ### Named Configs You can have multiple config files: ```java Config mainConfig = withConfig("main", MyConfig.CODEC); Config dbConfig = withConfig("database", DatabaseConfig.CODEC); ``` ## Required vs Optional Fields By default, all fields are **optional**. To make a field required, add a validator: ```java import com.hypixel.hytale.codec.validation.Validators; BuilderCodec.builder(MyConfig.class, MyConfig::new) .append(new KeyedCodec<>("ServerName", Codec.STRING), (config, val) -> config.serverName = val, config -> config.serverName) .addValidator(Validators.nonNull()) // Makes field required .add() .append(new KeyedCodec<>("MaxPlayers", Codec.INTEGER), (config, val) -> config.maxPlayers = val, config -> config.maxPlayers) .add() // Optional - uses default value from class .build(); ``` ## List and Map Codecs For collections: ```java import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.codec.codecs.map.ObjectMapCodec; // Array of strings Codec stringArray = new ArrayCodec<>(Codec.STRING, String[]::new); // Map with string keys Codec> stringIntMap = new ObjectMapCodec<>( Codec.INTEGER, LinkedHashMap::new, key -> key, // Key to string str -> str // String to key ); ``` ## Enum Codecs For enum types: ```java import com.hypixel.hytale.codec.codecs.EnumCodec; public enum GameMode { SURVIVAL, CREATIVE, ADVENTURE } Codec gameModeCodec = new EnumCodec<>(GameMode.class); ``` ## Nested Codecs Codecs can be nested for complex structures: ```java public class ServerSettings { private GeneralSettings general; private DatabaseSettings database; public static final BuilderCodec CODEC = BuilderCodec.builder(ServerSettings.class, ServerSettings::new) .append(new KeyedCodec<>("General", GeneralSettings.CODEC), (s, val) -> s.general = val, s -> s.general) .add() .append(new KeyedCodec<>("Database", DatabaseSettings.CODEC), (s, val) -> s.database = val, s -> s.database) .add() .build(); } ``` ## Inheritance Use parent codecs for class hierarchies: ```java // Base class codec public static final BuilderCodec BASE_CODEC = BuilderCodec.builder(BaseEntity.class, BaseEntity::new) .append(new KeyedCodec<>("Id", Codec.STRING), (e, val) -> e.id = val, e -> e.id) .add() .build(); // Child class codec inherits from parent public static final BuilderCodec CODEC = BuilderCodec.builder(PlayerEntity.class, PlayerEntity::new, BASE_CODEC) .append(new KeyedCodec<>("Username", Codec.STRING), (e, val) -> e.username = val, e -> e.username) .add() .build(); ``` ## Best Practices {{< callout type="tip" >}} - Define codecs as `public static final` fields - Use PascalCase for JSON keys (e.g., `"ServerName"`, not `"serverName"`) - Set default values in class field declarations - Use `Validators.nonNull()` for required fields - Keep configuration classes with simple setters for codec compatibility {{< /callout >}}