From 3f3d369f80350e9059ff85706b73e703b330ec7a Mon Sep 17 00:00:00 2001 From: Hani Rouatbi Date: Sun, 25 Jan 2026 13:07:14 +0100 Subject: [PATCH] Add HytaleONE protocol support Introduces a new protocol class for Hytale server querying, including response parsing for server info, players, and plugins. --- src/GameQ/Protocols/Hytaleone.php | 185 ++++++++++++++++++ tests/Protocols/Hytaleone.php | 49 +++++ .../Providers/Hytaleone/1_response.txt | Bin 0 -> 4355 bytes .../Providers/Hytaleone/1_result.json | 1 + .../Providers/Hytaleone/2_response.txt | Bin 0 -> 3799 bytes .../Providers/Hytaleone/2_result.json | 1 + 6 files changed, 236 insertions(+) create mode 100644 src/GameQ/Protocols/Hytaleone.php create mode 100644 tests/Protocols/Hytaleone.php create mode 100644 tests/Protocols/Providers/Hytaleone/1_response.txt create mode 100644 tests/Protocols/Providers/Hytaleone/1_result.json create mode 100644 tests/Protocols/Providers/Hytaleone/2_response.txt create mode 100644 tests/Protocols/Providers/Hytaleone/2_result.json 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 0000000000000000000000000000000000000000..cf7b3890081862b6260b69e6c5a7d184ac54c10f GIT binary patch literal 4355 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ead46b83fca146d6947ccf34a0d9d42f71e6f1e5 GIT binary patch literal 3799 zcma)9O>7%Q6kZG3N^PN(q(2l2?iDH4?mBi83q)flPJ-;jbe&e^g2uaJXYlNfHM^T) z!~v?RNCi|*^nwH@xR$n2gDBy~h0FTF2?@lN3kWVfmAC86vms^4!O>>t&3oVb-tR75 zI=|4UUD7g#v^8&@`9UaK)VZcbpGMo!H-j75=-X&B8{HYa8*L4)Mz^A`2UnuaGuh}f zc)k~HMfbCQk6iYqNH)5ijqbv&uRwM?J9uw!9e!7$?ZFMuu@!6C%0}P8;Uv2uf9Qb8kp43d;Ear40XHHKQsp(9&?R+r=!2|0bV;Bh5b5u7t0%%w>`t)%B^E9^9Q*kRtI^^U;yI14UNE^HR`A1ynfw666W z5~RXCr9|g!oBBR*6iC6-AR`mY0d>;^$9(H?(I+iVeMS8-Wws1{bS)a}Ns-l)%nPbQ z+Egh*y6dbXlQ8c|)12?8+eEs75nu3B4i775z%=Cw8Mq3cr4PULH|5tp*ljYhSjl1JqnZwsm@O-bFp6G z{VzwTuOfVx2F&);xJT4A+97s-Z=!Q6&@*iT9Q74SJdV2%3 z-~~`hX@H(m%p~dBWOjF#(Pb|HHto2-q-ny|H0(JIPWn{VU@oLxdQzEh5ZM(W1`Mf~ zb6bphqpH9pST<%-;T%$$t##2;K4Dy|yk8+MxRnMDX-~LWqJ#(QY4Xo0lTcY6wFBxT z7gIxph=%<4d#Uw^m6u4TVL@UqQWC6FBo_HQPkUjIv=v3p2?f6)#hU=1rS}F5Q8J34 zDzh$CcZcx^ciC9(kceAJCi z9^SglOHK0;$??Q$toMEBcM2q8iOXnr&fwj7;=+oN1{CKpEI)11vf|wjR+E&41D!xZ z$7>nsR`iXM9FxCFpkI#qC_+GmDIN{8cZgE4f!%W1^8*5H33YymXZ$R>sQDKi8*d3rrt;T?PDg4r+ zB(16xE`(Vbn$XH&__mQRlf?Db`(wg}%i@U0@drR48X*s={hXA}!l*2-MNT3T&pCbW4tUng&sR^zoN zAa<8JN7TY?m{WQEY~IM6)K*v^i6crd%G*N1l4Dbgz?B#yEbp1;HCwnjPHiqOdrml; zHwt=bsSjHn%<_aJGnda5GRL(thY9v7k<=+!%~i4Pdf^2yF8^&1V|)zRo(Gwxpo8USGAkjPoY^w@=e^(>XJv(qh%4rPsop?Ii|& zLR%CbtulWda-}r(9N#oS;H2izjhx3k`1WBosNbqnt&l@*Cx^zUbh5G QN6^m>zfEHP3%PveZ~F&yivR!s literal 0 HcmV?d00001 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