diff --git a/src/GameQ/Protocols/Hytaleone.php b/src/GameQ/Protocols/Hytaleone.php new file mode 100644 index 00000000..627681f8 --- /dev/null +++ b/src/GameQ/Protocols/Hytaleone.php @@ -0,0 +1,185 @@ +. + */ + +namespace GameQ\Protocols; + +use GameQ\Buffer; +use GameQ\Protocol; +use GameQ\Result; + +/** + * HytaleONE Protocol Class + * + * @author H.Rouatbi + */ +class Hytaleone extends Protocol +{ + /** + * Protocol Header + */ + const PACKET_HEADER = "HYREPLY\x00"; + + /** + * The protocol being used + * + * @var string + */ + protected $protocol = 'hytaleone'; + + /** + * String name of this protocol class + * + * @var string + */ + protected $name = 'hytaleone'; + + /** + * Longer string name of this protocol class + * + * @var string + */ + protected $name_long = "HytaleONE"; + + /** + * Array of packets we want to look up. + * + * @var array + */ + protected $packets = [ + // There's no need for the basic packet because we have the full packet. + //self::PACKET_BASIC => "HYQUERY\x00\x00", + self::PACKET_ALL => "HYQUERY\x00\x01", + ]; + + /** + * Normalize settings for this protocol + * + * @var array + */ + protected $normalize = [ + // General + 'general' => [ + 'hostname' => 'hostname', + 'numplayers' => 'num_players', + 'maxplayers' => 'max_players', + ], + // Individual + 'player' => [ + 'name' => 'name', + ], + ]; + + /** + * Process the response + * + * @return array + */ + public function processResponse() + { + $results = []; + + foreach ($this->packets_response as $response) { + $buffer = new Buffer($response); + + // Validate Magic + if ($buffer->read(8) !== self::PACKET_HEADER) { + continue; + } + + $type = $buffer->readInt8(); + $result = new Result(); + + // Basic Info + $result->add('hostname', $this->readString16($buffer)); + $result->add('motd', $this->readString16($buffer)); + $result->add('num_players', $buffer->readInt32()); + $result->add('max_players', $buffer->readInt32()); + $result->add('port', $buffer->readInt16()); + $result->add('version', $this->readString16($buffer)); + $result->add('protocol_version', $buffer->readInt32()); + $result->add('protocol_hash', $this->readString16($buffer)); + + if ($type === 0x01) { // Full + // Players + $playerCount = $buffer->readInt32(); + for ($i = 0; $i < $playerCount; $i++) { + $result->addPlayer('name', $this->readString16($buffer)); + $result->addPlayer('uuid', $this->readUUID($buffer)); + } + + // Plugins + $pluginCount = $buffer->readInt32(); + $plugins = []; + for ($i = 0; $i < $pluginCount; $i++) { + $plugins[] = [ + 'id' => $this->readString16($buffer), + 'version' => $this->readString16($buffer), + 'enabled' => $buffer->readInt8() !== 0, + ]; + } + $result->add('plugins', $plugins); + } + + $results = array_merge($results, $result->fetch()); + } + + return $results; + } + + /** + * Read a string with 2-byte length header + * + * @param Buffer $buffer + * @return string + */ + private function readString16(Buffer $buffer) + { + $length = $buffer->readInt16(); + return $buffer->read($length); + } + + /** + * Read UUID (Big Endian 128-bit integer rendered as hex string) + * + * @param Buffer $buffer + * @return string + */ + private function readUUID(Buffer $buffer) + { + // MSB (8 bytes) + $msb = unpack('J', $buffer->read(8))[1]; + // LSB (8 bytes) + $lsb = unpack('J', $buffer->read(8))[1]; + + // Convert to hex + $msbHex = sprintf('%016x', $msb); + $lsbHex = sprintf('%016x', $lsb); + + $hex = $msbHex . $lsbHex; + + // 8-4-4-4-12 format + return sprintf( + '%s-%s-%s-%s-%s', + substr($hex, 0, 8), + substr($hex, 8, 4), + substr($hex, 12, 4), + substr($hex, 16, 4), + substr($hex, 20) + ); + } +} diff --git a/tests/Protocols/Hytaleone.php b/tests/Protocols/Hytaleone.php new file mode 100644 index 00000000..3107a386 --- /dev/null +++ b/tests/Protocols/Hytaleone.php @@ -0,0 +1,49 @@ +. + */ + +namespace GameQ\Tests\Protocols; + +/** + * Test Class for HytaleONE + * + * @package GameQ\Tests\Protocols + */ +class Hytaleone extends Base +{ + /** + * Test responses for HytaleONE + * + * @dataProvider loadData + * + * @param $responses + * @param $result + */ + public function testResponses($responses, $result) + { + // Pull the first key off the array this is the server ip:port + $server = key($result); + + $testResult = $this->queryTest( + $server, + 'hytaleone', + $responses + ); + + $this->assertEquals($result[$server], $testResult); + } +} diff --git a/tests/Protocols/Providers/Hytaleone/1_response.txt b/tests/Protocols/Providers/Hytaleone/1_response.txt new file mode 100644 index 00000000..cf7b3890 Binary files /dev/null and b/tests/Protocols/Providers/Hytaleone/1_response.txt differ diff --git a/tests/Protocols/Providers/Hytaleone/1_result.json b/tests/Protocols/Providers/Hytaleone/1_result.json new file mode 100644 index 00000000..15c93a16 --- /dev/null +++ b/tests/Protocols/Providers/Hytaleone/1_result.json @@ -0,0 +1 @@ +{"193.233.248.212:5520":{"gq_address":"193.233.248.212","gq_joinlink":null,"gq_name":"HytaleONE","gq_online":true,"gq_port_client":5520,"gq_port_query":5520,"gq_protocol":"hytaleone","gq_transport":"udp","gq_type":"hytaleone","hostname":"Hytale Server","max_players":1000,"motd":"Лучший сервер в мире! Первый в России!","num_players":33,"players":[{"name":"ICMEPTb","uuid":"954024d2-03ec-4040-b3e7-9c16dede8d50"},{"name":"Space_Taurus","uuid":"53338768-113c-4162-b409-a737fa1827e2"},{"name":"BROSKO","uuid":"f8bf608d-9aca-49b9-ab85-fa74200935fe"},{"name":"Islam7878","uuid":"0a95d58c-3410-4fef-8f82-2ce10403c10e"},{"name":"FleetMesa157","uuid":"f8aabd97-9c9f-4627-b32b-5eaf5af3027b"},{"name":"Arifur","uuid":"19163e70-4889-4a5a-9120-115d300a0dcf"},{"name":"lisi4ka","uuid":"e9d8214c-57c1-4e2a-a41e-ce34326e9c6a"},{"name":"__Cookie__","uuid":"575f61aa-eca1-430d-a445-c0c72f0aea43"},{"name":"Jollylaps","uuid":"632cc467-e2db-44dd-971f-7ce8a15c18f5"},{"name":"bliznyashka","uuid":"6136c9ce-4e67-4f91-a420-1d78fb1605d7"},{"name":"Fei_Long","uuid":"f5f955dc-859b-43b1-976f-846fb311f889"},{"name":"N41X","uuid":"85848610-d186-4d68-90b1-bd0a526f6b74"},{"name":"Ashraa","uuid":"e906f07a-6a77-4b2a-a2b5-5d7c8d278593"},{"name":"ResoluteCliff797","uuid":"757801d8-7b30-43e7-baf5-d7dd2989e048"},{"name":"Mariska","uuid":"d488b6b5-f386-4717-afdb-8b5397798abd"},{"name":"TokEiMan","uuid":"7dc727bf-b921-4c76-9bc1-a5dc7ece4058"},{"name":"daniFX","uuid":"ad1a17e9-7a79-43b6-badf-653f106ee217"},{"name":"credo","uuid":"6e79a26b-ac73-419d-a86b-9816d5cdbb65"},{"name":"SwiftMoose374","uuid":"0a8234e7-36a2-4093-8fae-b8edeefa5246"},{"name":"Mandarinka","uuid":"24dbd120-25ec-4b80-a17a-be8664219ce6"},{"name":"3xnrnt","uuid":"8429b34d-7968-43b9-8934-cf0a4edb2b7f"},{"name":"wowikmur","uuid":"40e078a7-2a19-44d8-a100-b2c655b90216"},{"name":"DanyaPro405","uuid":"71367492-b8e0-4d65-afb6-be975d4cc13d"},{"name":"AlexR","uuid":"7a7bd1a2-565e-47b5-b1fb-bedc0d557eb6"},{"name":"_CAXAPOK_","uuid":"5690d909-57c5-473a-a170-a0cef5bde153"},{"name":"1nkvi","uuid":"9ef4f3d1-a817-487d-b63f-73134fdb03c0"},{"name":"im_chert42","uuid":"ae6030ee-a07c-4512-a68d-f3a7bac9dcf8"},{"name":"GG_and","uuid":"b21fff04-d94c-4041-b60b-443f61cc1552"},{"name":"_Les_","uuid":"44c435ea-61d2-4d37-946e-170a569d430f"},{"name":"Pelvit","uuid":"a81cbdd0-6516-4a52-bbd6-7b32bb3a75ab"},{"name":"Popochka","uuid":"8d09c737-37b0-4e48-9438-32dd34a71d79"},{"name":"NaturalTrail387","uuid":"9c030313-e397-476e-b084-c44a238e7597"},{"name":"Marlya","uuid":"d9d9a310-8b77-4791-9dcc-4ee2571a4424"}],"plugins":[{"id":"Hytale:WorldLocationCondition","version":"1.0.0","enabled":true},{"id":"Hytale:ServerManager","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:TimeModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:CollisionModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:DebugPlugin","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:SplitVelocity","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:UpdateModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:AccessControlModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ItemModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Deployables","version":"1.0.0","enabled":true},{"id":"Hytale:BlockSetModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:SprintForce","version":"1.0.0","enabled":true},{"id":"Hytale:MigrationModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:AssetModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ConsoleModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Model","version":"1.0.0","enabled":true},{"id":"Hytale:CrouchSlide","version":"1.0.0","enabled":true},{"id":"Hytale:Universe","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:TagSet","version":"1.0.0","enabled":true},{"id":"Hytale:CommandMacro","version":"1.0.0","enabled":true},{"id":"Hytale:SafetyRoll","version":"1.0.0","enabled":true},{"id":"Hytale:HytaleGenerator","version":"1.0.0","enabled":true},{"id":"Hytale:CommonAssetModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:CosmeticsModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:LegacyModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:LANDiscovery","version":"1.0.0","enabled":true},{"id":"Hytale:Mantling","version":"1.0.0","enabled":true},{"id":"Hytale:PermissionsModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:EntityModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockTick","version":"1.0.0","enabled":true},{"id":"Hytale:InteractionModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ServerPlayerListModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Parkour","version":"1.0.0","enabled":true},{"id":"Hytale:Ambience","version":"1.0.0","enabled":true},{"id":"Hytale:I18nModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Shop","version":"1.0.0","enabled":true},{"id":"Hytale:FlyCameraModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockHealthModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ConnectedBlocksModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockTypeModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Weather","version":"1.0.0","enabled":true},{"id":"Hytale:Reputation","version":"1.0.0","enabled":true},{"id":"Hytale:ProjectileModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:WorldGen","version":"1.0.0","enabled":true},{"id":"Hytale:BlockStateModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:AssetEditor","version":"1.0.0","enabled":true},{"id":"Hytale:BuilderTools","version":"1.0.0","enabled":true},{"id":"Hytale:Fluid","version":"1.0.0","enabled":true},{"id":"Hytale:Crafting","version":"1.0.0","enabled":true},{"id":"Hytale:SingleplayerModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:EntityStatsModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Objectives","version":"1.0.0","enabled":true},{"id":"Hytale:Path","version":"1.0.0","enabled":true},{"id":"Hytale:Teleport","version":"1.0.0","enabled":true},{"id":"Hytale:EntityUIModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Stash","version":"1.0.0","enabled":true},{"id":"Hytale:StaminaModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockPhysics","version":"1.0.0","enabled":true},{"id":"Hytale:ShopReputation","version":"1.0.0","enabled":true},{"id":"Hytale:DamageModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:PrefabSpawnerModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ObjectiveShop","version":"1.0.0","enabled":true},{"id":"Hytale:Teleporter","version":"1.0.0","enabled":true},{"id":"Hytale:Farming","version":"1.0.0","enabled":true},{"id":"Hytale:ObjectiveReputation","version":"1.0.0","enabled":true},{"id":"Hytale:BlockSpawner","version":"1.0.0","enabled":true},{"id":"Hytale:Instances","version":"1.0.0","enabled":true},{"id":"Hytale:Camera","version":"1.0.0","enabled":true},{"id":"Hytale:NPC","version":"1.0.0","enabled":true},{"id":"Hytale:Mounts","version":"1.0.0","enabled":true},{"id":"Hytale:NPCEditor","version":"1.0.0","enabled":true},{"id":"Hytale:Memories","version":"1.0.0","enabled":true},{"id":"Hytale:NPCShop","version":"1.0.0","enabled":true},{"id":"Hytale:NPCCombatActionEvaluator","version":"1.0.0","enabled":true},{"id":"Hytale:CreativeHub","version":"1.0.0","enabled":true},{"id":"Hytale:Spawning","version":"1.0.0","enabled":true},{"id":"Hytale:NPCObjectives","version":"1.0.0","enabled":true},{"id":"Hytale:Flock","version":"1.0.0","enabled":true},{"id":"Hytale:Beds","version":"1.0.0","enabled":true},{"id":"Hytale:Portals","version":"1.0.0","enabled":true},{"id":"Hytale:NPCReputation","version":"1.0.0","enabled":true},{"id":"ehko:Hylograms","version":"1.0.0","enabled":true},{"id":"tins:HyAnnouncer","version":"1.1.5","enabled":true},{"id":"Economy:EconomySystem","version":"1.0.0","enabled":true},{"id":"com.nhulston:Essentials","version":"1.5.2","enabled":true},{"id":"Buuz135:MultipleHUD","version":"1.0.3","enabled":true},{"id":"Playtime:Playtime","version":"1.2.0","enabled":true},{"id":"Shiirroo:TPS","version":"1.0.4","enabled":true},{"id":":NPC Dialog","version":"1.1.3","enabled":true},{"id":"BlameJared:SimplyTrash","version":"1.0.0","enabled":true},{"id":"CORE:CoreProtect","version":"1.3.0","enabled":true},{"id":"HytaleOne:Query","version":"1.1.0","enabled":true},{"id":"jamo:serverfixes","version":"1.1.2","enabled":true},{"id":"Buuz135:SimpleClaims","version":"1.0.16","enabled":true},{"id":"LuckPerms:LuckPerms","version":"5.5.24","enabled":true},{"id":"Devify:ProximityCore","version":"1.1.4","enabled":true},{"id":"leniad:TextSigns","version":"1.0.2","enabled":true},{"id":"Zuxaw:RPGLeveling","version":"0.1.8","enabled":true}],"port":5520,"protocol_hash":"6708f121966c1c443f4b0eb525b2f81d0a8dc61f5003a692a8fa157e5e02cea9","protocol_version":1,"version":"2026.01.24-6e2d4fc36"}} \ No newline at end of file diff --git a/tests/Protocols/Providers/Hytaleone/2_response.txt b/tests/Protocols/Providers/Hytaleone/2_response.txt new file mode 100644 index 00000000..ead46b83 Binary files /dev/null and b/tests/Protocols/Providers/Hytaleone/2_response.txt differ diff --git a/tests/Protocols/Providers/Hytaleone/2_result.json b/tests/Protocols/Providers/Hytaleone/2_result.json new file mode 100644 index 00000000..50ce0d3b --- /dev/null +++ b/tests/Protocols/Providers/Hytaleone/2_result.json @@ -0,0 +1 @@ +{"170.23.138.37:15617":{"gq_address":"170.23.138.37","gq_joinlink":null,"gq_name":"HytaleONE","gq_online":true,"gq_port_client":15617,"gq_port_query":15617,"gq_protocol":"hytaleone","gq_transport":"udp","gq_type":"hytaleone","hostname":"UnDisturbed","max_players":100,"motd":"Моля не грифайте! Пазим spawn-a в добро състояние и предмети за новите играчи","num_players":4,"players":[{"name":"Sikoman","uuid":"b2008af9-dcc6-4d6b-a697-4fb316a74cb4"},{"name":"Dimakis","uuid":"428cb484-f11d-4061-a08a-fff3eb0ae23f"},{"name":"Preslav","uuid":"6721d177-e0f0-4f3c-86f4-ffdf0bff7232"},{"name":"IronSlope131","uuid":"972a8dcb-90f9-4662-9603-01578b457cd6"}],"plugins":[{"id":"Hytale:WorldLocationCondition","version":"1.0.0","enabled":true},{"id":"Hytale:ServerManager","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:TimeModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:CollisionModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:DebugPlugin","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:SplitVelocity","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:UpdateModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:AccessControlModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ItemModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Deployables","version":"1.0.0","enabled":true},{"id":"Hytale:BlockSetModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:SprintForce","version":"1.0.0","enabled":true},{"id":"Hytale:MigrationModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:AssetModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ConsoleModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Model","version":"1.0.0","enabled":true},{"id":"Hytale:CrouchSlide","version":"1.0.0","enabled":true},{"id":"Hytale:Universe","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:TagSet","version":"1.0.0","enabled":true},{"id":"Hytale:CommandMacro","version":"1.0.0","enabled":true},{"id":"Hytale:SafetyRoll","version":"1.0.0","enabled":true},{"id":"Hytale:HytaleGenerator","version":"1.0.0","enabled":true},{"id":"Hytale:CommonAssetModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:CosmeticsModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:LegacyModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:LANDiscovery","version":"1.0.0","enabled":true},{"id":"Hytale:Mantling","version":"1.0.0","enabled":true},{"id":"Hytale:PermissionsModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:EntityModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockTick","version":"1.0.0","enabled":true},{"id":"Hytale:InteractionModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ServerPlayerListModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Parkour","version":"1.0.0","enabled":true},{"id":"Hytale:Ambience","version":"1.0.0","enabled":true},{"id":"Hytale:I18nModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Shop","version":"1.0.0","enabled":true},{"id":"Hytale:FlyCameraModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockHealthModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ConnectedBlocksModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockTypeModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Weather","version":"1.0.0","enabled":true},{"id":"Hytale:Reputation","version":"1.0.0","enabled":true},{"id":"Hytale:ProjectileModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:WorldGen","version":"1.0.0","enabled":true},{"id":"Hytale:BlockStateModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:AssetEditor","version":"1.0.0","enabled":true},{"id":"Hytale:BuilderTools","version":"1.0.0","enabled":true},{"id":"Hytale:Fluid","version":"1.0.0","enabled":true},{"id":"Hytale:Crafting","version":"1.0.0","enabled":true},{"id":"Hytale:SingleplayerModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:EntityStatsModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Objectives","version":"1.0.0","enabled":true},{"id":"Hytale:Path","version":"1.0.0","enabled":true},{"id":"Hytale:Teleport","version":"1.0.0","enabled":true},{"id":"Hytale:EntityUIModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:Stash","version":"1.0.0","enabled":true},{"id":"Hytale:StaminaModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:BlockPhysics","version":"1.0.0","enabled":true},{"id":"Hytale:ShopReputation","version":"1.0.0","enabled":true},{"id":"Hytale:DamageModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:PrefabSpawnerModule","version":"2026.1.24-6e2d4fc36","enabled":true},{"id":"Hytale:ObjectiveShop","version":"1.0.0","enabled":true},{"id":"Hytale:Teleporter","version":"1.0.0","enabled":true},{"id":"Hytale:Farming","version":"1.0.0","enabled":true},{"id":"Hytale:ObjectiveReputation","version":"1.0.0","enabled":true},{"id":"Hytale:BlockSpawner","version":"1.0.0","enabled":true},{"id":"Hytale:Instances","version":"1.0.0","enabled":true},{"id":"Hytale:Camera","version":"1.0.0","enabled":true},{"id":"Hytale:NPC","version":"1.0.0","enabled":true},{"id":"Hytale:Mounts","version":"1.0.0","enabled":true},{"id":"Hytale:NPCEditor","version":"1.0.0","enabled":true},{"id":"Hytale:Memories","version":"1.0.0","enabled":true},{"id":"Hytale:NPCShop","version":"1.0.0","enabled":true},{"id":"Hytale:NPCCombatActionEvaluator","version":"1.0.0","enabled":true},{"id":"Hytale:CreativeHub","version":"1.0.0","enabled":true},{"id":"Hytale:Spawning","version":"1.0.0","enabled":true},{"id":"Hytale:NPCObjectives","version":"1.0.0","enabled":true},{"id":"Hytale:Flock","version":"1.0.0","enabled":true},{"id":"Hytale:Beds","version":"1.0.0","enabled":true},{"id":"Hytale:Portals","version":"1.0.0","enabled":true},{"id":"Hytale:NPCReputation","version":"1.0.0","enabled":true},{"id":"Linceros:GrabFromFar","version":"1.0.0","enabled":true},{"id":"Buuz135:MultipleHUD","version":"1.0.3","enabled":true},{"id":"HSL:Votifier","version":"1.6.1","enabled":true},{"id":"Ender_Griefeur99:HealthBar","version":"1.0.6","enabled":true},{"id":"spark:spark","version":"1.10.165-SNAPSHOT","enabled":true},{"id":"Darkhax:Overstacked","version":"2026.1.12-30731","enabled":true},{"id":"Nitrado:PerformanceSaver","version":"1.1.0","enabled":true},{"id":"com.leclowndu93150:Hyssentials","version":"2.3.5","enabled":true},{"id":"BlameJared:SimplyTrash","version":"1.0.0","enabled":true},{"id":"Ev0sMods:Ev0Lib","version":"1.2.5","enabled":true},{"id":"Buuz135:BetterModlist","version":"1.0.4","enabled":true},{"id":"Ziggfreed:MMOSkillTree","version":"0.4.2","enabled":true},{"id":"HytaleOne:Query","version":"1.1.0","enabled":true},{"id":"GoneFishing:GoneFishing","version":"0.2.0","enabled":true},{"id":"dev.ninesliced:BetterMap","version":"1.2.6","enabled":true},{"id":"LuckPerms:LuckPerms","version":"5.5.24","enabled":true},{"id":"GilloDaby:Better ScoreBoard","version":"1.6.1","enabled":true},{"id":"Buuz135:SimpleClaims","version":"1.0.22","enabled":true},{"id":"com.carsonk:Party Plugin","version":"1.5.3","enabled":true}],"port":15617,"protocol_hash":"6708f121966c1c443f4b0eb525b2f81d0a8dc61f5003a692a8fa157e5e02cea9","protocol_version":1,"version":"2026.01.24-6e2d4fc36"}} \ No newline at end of file