├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── crash.md └── workflows │ └── php-cs-fixer.yml ├── .gitignore ├── .php-cs-fixer.php ├── README.md ├── composer.json ├── plugin.yml ├── resources ├── config.yml └── versions │ ├── block_state_meta_map-1.20.50.json │ ├── block_state_meta_map-1.20.60.json │ ├── block_state_meta_map-1.20.70.json │ ├── block_state_meta_map-1.20.80.json │ ├── block_state_meta_map-1.21.2.json │ ├── block_state_meta_map-1.21.20.json │ ├── block_state_meta_map-1.21.30.json │ ├── block_state_meta_map-1.21.40.json │ ├── block_state_meta_map-1.21.50.json │ ├── block_state_meta_map-1.21.60.json │ ├── canonical_block_states-1.20.50.nbt │ ├── canonical_block_states-1.20.60.nbt │ ├── canonical_block_states-1.20.70.nbt │ ├── canonical_block_states-1.20.80.nbt │ ├── canonical_block_states-1.21.2.nbt │ ├── canonical_block_states-1.21.20.nbt │ ├── canonical_block_states-1.21.30.nbt │ ├── canonical_block_states-1.21.40.nbt │ ├── canonical_block_states-1.21.50.nbt │ ├── canonical_block_states-1.21.60.nbt │ ├── required_item_list-1.20.50.json │ ├── required_item_list-1.20.60.json │ ├── required_item_list-1.20.70.json │ ├── required_item_list-1.20.80.json │ ├── required_item_list-1.21.2.json │ ├── required_item_list-1.21.20.json │ ├── required_item_list-1.21.30.json │ ├── required_item_list-1.21.40.json │ ├── required_item_list-1.21.50.json │ └── required_item_list-1.21.60.json ├── scripts ├── fetch-nethergames.php └── gen-packet.php └── src └── Supero └── NightfallProtocol ├── Main.php ├── network ├── CustomNetworkSession.php ├── CustomProtocolInfo.php ├── CustomRaklibInterface.php ├── CustomStandardEntityEventBroadcaster.php ├── CustomStandardPacketBroadcaster.php ├── caches │ ├── CustomCraftingDataCache.php │ └── CustomCreativeInventoryCache.php ├── chunk │ ├── CustomChunkCache.php │ ├── CustomChunkRequestTask.php │ └── serializer │ │ └── CustomChunkSerializer.php ├── compression │ └── CompressBatchTask.php ├── handlers │ ├── CustomLoginPacketHandler.php │ ├── CustomPreSpawnPacketHandler.php │ ├── CustomSessionStartPacketHandler.php │ └── static │ │ ├── InGamePacketHandler.php │ │ ├── ItemStackRequestExecutor.php │ │ └── ItemStackResponseBuilder.php ├── packets │ ├── CameraAimAssistPacket.php │ ├── CameraAimAssistPresetsPacket.php │ ├── CameraInstructionPacket.php │ ├── CameraPresetsPacket.php │ ├── ChangeDimensionPacket.php │ ├── ClientMovementPredictionSyncPacket.php │ ├── CodeBuilderSourcePacket.php │ ├── ContainerClosePacket.php │ ├── CreativeContentPacket.php │ ├── DisconnectPacket.php │ ├── EditorNetworkPacket.php │ ├── EmotePacket.php │ ├── InventoryContentPacket.php │ ├── InventorySlotPacket.php │ ├── InventoryTransactionPacket.php │ ├── ItemRegistryPacket.php │ ├── ItemStackRequestPacket.php │ ├── ItemStackResponsePacket.php │ ├── LecternUpdatePacket.php │ ├── LevelChunkPacket.php │ ├── LevelSoundEventPacket.php │ ├── MobArmorEquipmentPacket.php │ ├── MobEffectPacket.php │ ├── PlayerArmorDamagePacket.php │ ├── PlayerAuthInputPacket.php │ ├── PlayerAuthInputVehicleInfo.php │ ├── PlayerListPacket.php │ ├── ResourcePackStackPacket.php │ ├── ResourcePacksInfoPacket.php │ ├── SetActorMotionPacket.php │ ├── SetHudPacket.php │ ├── SetTitlePacket.php │ ├── StartGamePacket.php │ ├── StopSoundPacket.php │ ├── TextPacket.php │ ├── TickSyncPacket.php │ ├── TransferPacket.php │ ├── UpdateAbilitiesPacket.php │ ├── UpdateAttributesPacket.php │ ├── UpdatePlayerGameTypePacket.php │ ├── serializer │ │ └── CustomBitSet.php │ └── types │ │ ├── AbilitiesData.php │ │ ├── AbilitiesLayer.php │ │ ├── CustomItemInteractionData.php │ │ ├── CustomLevelSettings.php │ │ ├── CustomUpdateAttribute.php │ │ ├── camera │ │ └── CustomCameraPreset.php │ │ ├── inventory │ │ ├── CreativeItemEntry.php │ │ ├── CustomItemStackRequest.php │ │ ├── CustomUseItemTransactionData.php │ │ ├── FullContainerName.php │ │ ├── stackrequest │ │ │ ├── CraftRecipeAutoStackRequestAction.php │ │ │ ├── CraftRecipeStackRequestAction.php │ │ │ ├── CraftingConsumeInputStackRequestAction.php │ │ │ ├── CreativeCreateStackRequestAction.php │ │ │ ├── DestroyStackRequestAction.php │ │ │ ├── DisappearStackRequestActionTrait.php │ │ │ ├── DropStackRequestAction.php │ │ │ ├── GrindstoneStackRequestAction.php │ │ │ ├── ItemStackRequestSlotInfo.php │ │ │ ├── PlaceIntoBundleStackRequestAction.php │ │ │ ├── PlaceStackRequestAction.php │ │ │ ├── SwapStackRequestAction.php │ │ │ ├── TakeFromBundleStackRequestAction.php │ │ │ ├── TakeOrPlaceStackRequestActionTrait.php │ │ │ └── TakeStackRequestAction.php │ │ └── stackresponse │ │ │ ├── ItemStackResponse.php │ │ │ ├── ItemStackResponseContainerInfo.php │ │ │ └── ItemStackResponseSlotInfo.php │ │ ├── recipe │ │ ├── CustomShapedRecipe.php │ │ └── CustomShapelessRecipe.php │ │ └── resourcepacks │ │ ├── CustomBehaviourPackInfoEntry.php │ │ └── CustomResourcePackInfoEntry.php └── static │ ├── CustomPacketBatch.php │ ├── CustomPacketPool.php │ ├── CustomPacketSerializer.php │ ├── CustomRuntimeIDtoStateID.php │ ├── PacketConverter.php │ ├── convert │ ├── CustomBlockStateDictionary.php │ ├── CustomBlockStateDictionaryEntry.php │ ├── CustomBlockTranslator.php │ ├── CustomItemIdMetaDowngrader.php │ ├── CustomItemTranslator.php │ ├── CustomItemTypeDictionaryFromDataHelper.php │ └── CustomTypeConverter.php │ └── data │ ├── CustomGlobalItemDataHandlers.php │ ├── CustomItemSerializer.php │ ├── CustomItemSerializerDeserializerRegistrar.php │ └── bedrock │ ├── ItemTagDowngrader.php │ └── ItemTagToIdMap.php └── utils ├── ProtocolSingletonTrait.php ├── ProtocolUtils.php ├── ReflectionUtils.php └── Utils.php /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Unexpected non-crash behaviour 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | ### Issue description 10 | 11 | 12 | - Issue name: 13 | - Issue description: 14 | 15 | 16 | 17 | - Expected result: What were you expecting to happen? 18 | 19 | 20 | 21 | - Actual result: What actually happened? 22 | 23 | ### Versions 24 | 25 | 26 | 27 | - Version: X.XX.XX 28 | 29 | 30 | - Server Version: X.XX.X -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/crash.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Crash 3 | about: Report a crash in NightfallProtocol 4 | title: Server crashed 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | 10 | 11 | 12 | Link to crashdump: 13 | 14 | 15 | ### Additional comments (optional) -------------------------------------------------------------------------------- /.github/workflows/php-cs-fixer.yml: -------------------------------------------------------------------------------- 1 | name: PHP CS Fixer 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | name: Check 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | php: 16 | - "8.3" 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Setup PHP 22 | uses: shivammathur/setup-php@2.21.1 23 | with: 24 | php-version: ${{ matrix.php }} 25 | 26 | - name: Restore Composer package cache 27 | id: composer-cache 28 | uses: actions/cache@v3 29 | with: 30 | path: "~/.cache/composer" 31 | key: "php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}" 32 | restore-keys: "php-${{ matrix.php }}-composer-" 33 | 34 | - name: Install Composer dependencies 35 | run: composer install --prefer-dist --no-interaction --ignore-platform-reqs 36 | 37 | codestyle: 38 | name: Code Style checks 39 | runs-on: ubuntu-20.04 40 | strategy: 41 | fail-fast: false 42 | 43 | steps: 44 | - uses: actions/checkout@v4 45 | 46 | - name: Setup PHP and tools 47 | uses: shivammathur/setup-php@2.31.1 48 | with: 49 | php-version: 8.3 50 | tools: php-cs-fixer:3.65 51 | env: 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | 54 | - name: Checkout main branch 55 | run: | 56 | git fetch origin 57 | git checkout main || git checkout -b main origin/main 58 | 59 | - name: Run PHP-CS-Fixer 60 | run: php-cs-fixer fix --diff --ansi 61 | 62 | - name: Commit changes 63 | run: | 64 | git config --global user.name "GitHub Actions" 65 | git config --global user.email "actions@github.com" 66 | git add . 67 | git commit -m "Apply PHP CS Fixer changes" || echo "No changes to commit" 68 | 69 | - name: Push changes 70 | uses: ad-m/github-push-action@v0.6.0 71 | with: 72 | github_token: ${{ secrets.GITHUB_TOKEN }} 73 | branch: main 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | composer.lock 4 | .DS_Store 5 | .php-cs-fixer.cache -------------------------------------------------------------------------------- /.php-cs-fixer.php: -------------------------------------------------------------------------------- 1 | in(__DIR__ . '/src'); 5 | 6 | return (new PhpCsFixer\Config) 7 | ->setRiskyAllowed(true) 8 | ->setUsingCache(false) 9 | ->setRules([ 10 | 'align_multiline_comment' => [ 11 | 'comment_type' => 'phpdocs_only' 12 | ], 13 | 'array_indentation' => true, 14 | 'array_syntax' => [ 15 | 'syntax' => 'short' 16 | ], 17 | 'binary_operator_spaces' => [ 18 | 'default' => 'single_space' 19 | ], 20 | 'blank_line_after_namespace' => true, 21 | 'blank_line_after_opening_tag' => true, 22 | 'blank_line_before_statement' => [ 23 | 'statements' => [ 24 | 'declare' 25 | ] 26 | ], 27 | 'cast_spaces' => [ 28 | 'space' => 'single' 29 | ], 30 | 'concat_space' => [ 31 | 'spacing' => 'one' 32 | ], 33 | 'declare_strict_types' => true, 34 | 'elseif' => true, 35 | 'fully_qualified_strict_types' => true, 36 | 'global_namespace_import' => [ 37 | 'import_constants' => true, 38 | 'import_functions' => true, 39 | 'import_classes' => null, 40 | ], 41 | 'indentation_type' => true, 42 | 'logical_operators' => true, 43 | 'native_constant_invocation' => [ 44 | 'scope' => 'namespaced' 45 | ], 46 | 'native_function_invocation' => [ 47 | 'scope' => 'namespaced', 48 | 'include' => ['@all'], 49 | ], 50 | 'new_with_braces' => [ 51 | 'named_class' => true, 52 | 'anonymous_class' => false, 53 | ], 54 | 'no_closing_tag' => true, 55 | 'no_empty_phpdoc' => true, 56 | 'no_extra_blank_lines' => true, 57 | 'no_superfluous_phpdoc_tags' => [ 58 | 'allow_mixed' => true, 59 | ], 60 | 'no_trailing_whitespace' => true, 61 | 'no_trailing_whitespace_in_comment' => true, 62 | 'no_whitespace_in_blank_line' => true, 63 | 'no_unused_imports' => true, 64 | 'ordered_imports' => [ 65 | 'imports_order' => [ 66 | 'class', 67 | 'function', 68 | 'const', 69 | ], 70 | 'sort_algorithm' => 'alpha' 71 | ], 72 | 'phpdoc_align' => [ 73 | 'align' => 'vertical', 74 | 'tags' => [ 75 | 'param', 76 | ] 77 | ], 78 | 'phpdoc_line_span' => [ 79 | 'property' => 'single', 80 | 'method' => null, 81 | 'const' => null 82 | ], 83 | 'phpdoc_trim' => true, 84 | 'phpdoc_trim_consecutive_blank_line_separation' => true, 85 | 'return_type_declaration' => [ 86 | 'space_before' => 'one' 87 | ], 88 | 'single_blank_line_at_eof' => true, 89 | 'single_import_per_statement' => true, 90 | 'strict_param' => true, 91 | 'unary_operator_spaces' => true 92 | ]) 93 | ->setFinder($finder) 94 | ->setIndent("\t") 95 | ->setLineEnding("\n"); 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### NightfallProtocols 2 | 3 | (not-so) Simple multi-version base to support older versions. 4 | 5 | Replacement of [NetherGames MultiVersion](https://github.com/NetherGamesMC/PocketMine-MP) for people who can't use it 6 | 7 | ### Versions 8 | 9 | Currently, the plugin supports these versions: 10 | - 1.21.70 (`786`) 11 | - 1.21.60 (`776`) 12 | - 1.21.50 (`766`) 13 | - 1.21.40 (`748`) 14 | - 1.21.30 (`729`) 15 | - 1.21.20 (`712`) 16 | - 1.21.2 (`686`) 17 | - 1.21.0 (`685`) 18 | - 1.20.80 (`671`) 19 | - 1.20.70 (`662`) 20 | - 1.20.60 (`649`) 21 | - 1.20.50 (`630`) 22 | 23 | ### Discord 24 | 25 | Need help or want to help? 26 | 27 | Come join us in our [discord](https://discord.gg/dbFjhHqZpn) server! 28 | 29 | ### Contribution 30 | 31 | We welcome contributions to NightfallProtocols! Whether you're fixing a bug, proposing new features, or improving documentation, your contributions is valuable to us. 32 | 33 | ### Huge thanks to 34 | 35 | - [Flonja](https://github.com/Flonja) for bearing with me over the months and helping with previous attempts as well as his [multiversion](https://github.com/Flonja/multiversion) 36 | - [glance](https://github.com/glancist) for the help with un-seen item translation (crafting data and creative content packets) 37 | - [jack](https://github.com/didntpot) for the help with compression for 1.20.50 38 | 39 | And contributors who have worked on this project by making issues and pull requests! 40 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nightfall-mcpe/nightfallprotocols", 3 | "description": "(not-so) Simple multi-version plugin", 4 | "minimum-stability": "stable", 5 | "license": "proprietary", 6 | "authors": [ 7 | { 8 | "name": "superomarking", 9 | "email": "superomarking@outlook.com" 10 | } 11 | ], 12 | "require-dev": { 13 | "pocketmine/pocketmine-mp": "*", 14 | "friendsofphp/php-cs-fixer": "*" 15 | }, 16 | "require": { 17 | "ext-curl": "*" 18 | } 19 | } -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: NightfallProtocol 3 | version: 1.0 4 | main: Supero\NightfallProtocol\Main 5 | api: 5.0.0 6 | mcpe-protocol: 786 7 | ... 8 | -------------------------------------------------------------------------------- /resources/config.yml: -------------------------------------------------------------------------------- 1 | debug-mode: false -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.20.50.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.20.50.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.20.60.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.20.60.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.20.70.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.20.70.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.20.80.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.20.80.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.21.2.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.21.2.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.21.20.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.21.20.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.21.30.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.21.30.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.21.40.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.21.40.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.21.50.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.21.50.nbt -------------------------------------------------------------------------------- /resources/versions/canonical_block_states-1.21.60.nbt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nightfall-MCPE/NightfallProtocols/532b30bf2d63aa08289dbc218f42d6c0b42094f8/resources/versions/canonical_block_states-1.21.60.nbt -------------------------------------------------------------------------------- /scripts/fetch-nethergames.php: -------------------------------------------------------------------------------- 1 | "WARNING", 34 | PacketViolationWarningPacket::SEVERITY_FINAL_WARNING => "FINAL WARNING", 35 | PacketViolationWarningPacket::SEVERITY_TERMINATING_CONNECTION => "TERMINATION", 36 | ]; 37 | 38 | public static function getProtocolDataFolder() : string 39 | { 40 | return dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . "resources" . DIRECTORY_SEPARATOR . "versions"; 41 | } 42 | 43 | /** 44 | * @throws ReflectionException 45 | */ 46 | protected function onEnable() : void 47 | { 48 | $server = $this->getServer(); 49 | 50 | $regInterface = function(Server $server, bool $ipV6){ 51 | $typeConverter = CustomTypeConverter::getProtocolInstance(); 52 | $packetBroadcaster = new StandardPacketBroadcaster(Server::getInstance()); 53 | $entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster, $typeConverter); 54 | $server->getNetwork()->registerInterface(new CustomRaklibInterface( 55 | $server, 56 | $ipV6 ? $server->getIpv6() : $server->getIp(), 57 | $server->getPort(), 58 | $ipV6, 59 | $packetBroadcaster, 60 | $entityEventBroadcaster, 61 | $typeConverter 62 | )); 63 | }; 64 | 65 | ($regInterface)($server, false); 66 | if($server->getConfigGroup()->getConfigBool("enable-ipv6", true)){ 67 | ($regInterface)($server, true); 68 | } 69 | 70 | $server->getPluginManager()->registerEvent(NetworkInterfaceRegisterEvent::class, function(NetworkInterfaceRegisterEvent $event) : void{ 71 | $interface = $event->getInterface(); 72 | if($interface instanceof CustomRaklibInterface || (!$interface instanceof RakLibInterface && !$interface instanceof DedicatedQueryNetworkInterface)){ 73 | return; 74 | } 75 | 76 | $this->getLogger()->debug("Prevented network interface " . get_class($interface) . " from being registered"); 77 | $event->cancel(); 78 | }, EventPriority::NORMAL, $this); 79 | 80 | if($this->getConfig()->get("debug-mode")){ 81 | $server->getPluginManager()->registerEvent(DataPacketReceiveEvent::class, function(DataPacketReceiveEvent $event) : void{ 82 | $packet = $event->getPacket(); 83 | if($packet instanceof PacketViolationWarningPacket){ 84 | $this->getLogger()->debug("Packet Violation (" . self::PACKET_VIOLATION_WARNING_SEVERITY[$packet->getSeverity()] . ") from {$event->getOrigin()->getDisplayName()} message: '{$packet->getMessage()}' Packet ID: 0x" . str_pad(dechex($packet->getPacketId()), 2, "0", STR_PAD_LEFT)); 85 | } 86 | //if(!$packet instanceof PlayerAuthInputPacket) $this->getLogger()->debug("Received " . $packet::class . " from " . $event->getOrigin()->getDisplayName()); 87 | }, EventPriority::NORMAL, $this); 88 | $server->getPluginManager()->registerEvent(DataPacketSendEvent::class, function(DataPacketSendEvent $event) : void{ 89 | foreach($event->getTargets() as $target){ 90 | foreach($event->getPackets() as $packet){ 91 | $this->getLogger()->debug("Sending " . $packet::class . " to " . $target->getDisplayName()); 92 | } 93 | } 94 | }, EventPriority::NORMAL, $this); 95 | } 96 | 97 | CustomPacketPool::getInstance(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/CustomProtocolInfo.php: -------------------------------------------------------------------------------- 1 | getSessionManager(), 25 | CustomPacketPool::getInstance(), 26 | new RakLibPacketSender($sessionId, $this), 27 | ReflectionUtils::getProperty(RakLibInterface::class, $this, "packetBroadcaster"), 28 | ReflectionUtils::getProperty(RakLibInterface::class, $this, "entityEventBroadcaster"), 29 | ZlibCompressor::getInstance(), 30 | ReflectionUtils::getProperty(RakLibInterface::class, $this, "typeConverter"), 31 | $address, 32 | $port 33 | ); 34 | 35 | $sessions = ReflectionUtils::getProperty(RakLibInterface::class, $this, "sessions"); 36 | $sessions[$sessionId] = $session; 37 | ReflectionUtils::setProperty(RakLibInterface::class, $this, "sessions", $sessions); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/CustomStandardPacketBroadcaster.php: -------------------------------------------------------------------------------- 1 | call(); 33 | if($ev->isCancelled()){ 34 | return; 35 | } 36 | $packets = $ev->getPackets(); 37 | } 38 | 39 | $compressors = []; 40 | 41 | /** @var NetworkSession[][] $targetsByCompressor */ 42 | $targetsByCompressor = []; 43 | foreach($recipients as $recipient){ 44 | $compressor = $recipient->getCompressor(); 45 | $compressors[spl_object_id($compressor)] = $compressor; 46 | 47 | $targetsByCompressor[spl_object_id($compressor)][] = $recipient; 48 | } 49 | 50 | $totalLength = 0; 51 | $packetBuffers = []; 52 | foreach($packets as $packet){ 53 | $packet = PacketConverter::handleClientbound($packet, CustomTypeConverter::getProtocolInstance($this->protocolId), null); 54 | $encoder = CustomPacketSerializer::encoder(); 55 | $encoder->setProtocol($this->protocolId); 56 | 57 | $buffer = NetworkSession::encodePacketTimed($encoder, $packet); 58 | //varint length prefix + packet buffer 59 | $totalLength += (((int) log(strlen($buffer), 128)) + 1) + strlen($buffer); 60 | $packetBuffers[] = $buffer; 61 | } 62 | 63 | foreach($targetsByCompressor as $compressorId => $compressorTargets){ 64 | $compressor = $compressors[$compressorId]; 65 | 66 | $threshold = $compressor->getCompressionThreshold(); 67 | if(count($compressorTargets) > 1 && $threshold !== null && $totalLength >= $threshold){ 68 | //do not prepare shared batch unless we're sure it will be compressed 69 | $stream = new BinaryStream(); 70 | CustomPacketBatch::encodeRaw($stream, $packetBuffers); 71 | $batchBuffer = $stream->getBuffer(); 72 | 73 | $batch = ProtocolUtils::prepareBatch($batchBuffer, $compressor, $this->server, $this->protocolId, timings: Timings::$playerNetworkSendCompressBroadcast); 74 | foreach($compressorTargets as $target){ 75 | $target->queueCompressed($batch); 76 | } 77 | }else{ 78 | foreach($compressorTargets as $target){ 79 | foreach($packetBuffers as $packetBuffer){ 80 | $target->addToSendBuffer($packetBuffer); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/chunk/CustomChunkRequestTask.php: -------------------------------------------------------------------------------- 1 | */ 31 | protected NonThreadSafeValue $compressor; 32 | private string $tiles; 33 | protected int $protocol; 34 | 35 | /** 36 | * @phpstan-param DimensionIds::* $dimensionId 37 | */ 38 | public function __construct(int $chunkX, int $chunkZ, int $dimensionId, Chunk $chunk, CompressBatchPromise $promise, Compressor $compressor, int $protocol){ 39 | $this->compressor = new NonThreadSafeValue($compressor); 40 | 41 | $this->chunk = FastChunkSerializer::serializeTerrain($chunk); 42 | $this->chunkX = $chunkX; 43 | $this->chunkZ = $chunkZ; 44 | $this->dimensionId = $dimensionId; 45 | $this->tiles = CustomChunkSerializer::serializeTiles($chunk); 46 | $this->protocol = $protocol; 47 | 48 | $this->storeLocal(self::TLS_KEY_PROMISE, $promise); 49 | } 50 | 51 | public function onRun() : void{ 52 | $chunk = FastChunkSerializer::deserializeTerrain($this->chunk); 53 | $dimensionId = $this->dimensionId; 54 | 55 | $subCount = CustomChunkSerializer::getSubChunkCount($chunk, $dimensionId); 56 | $converter = CustomTypeConverter::getProtocolInstance($this->protocol); 57 | $payload = CustomChunkSerializer::serializeFullChunk($chunk, $dimensionId, $converter->getCustomBlockTranslator(), $this->protocol, $this->tiles); 58 | 59 | $stream = new BinaryStream(); 60 | 61 | CustomPacketBatch::encodePackets($this->protocol, $stream, [LevelChunkPacket::createPacket(new ChunkPosition($this->chunkX, $this->chunkZ), $dimensionId, $subCount, false, null, $payload)]); 62 | 63 | $compressor = $this->compressor->deserialize(); 64 | $this->setResult(($this->protocol >= CustomProtocolInfo::PROTOCOL_1_20_60 ? chr($compressor->getNetworkId()) : '') . $compressor->compress($stream->getBuffer())); 65 | } 66 | 67 | public function onCompletion() : void{ 68 | /** @var CompressBatchPromise $promise */ 69 | $promise = $this->fetchLocal(self::TLS_KEY_PROMISE); 70 | $promise->resolve($this->getResult()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/compression/CompressBatchTask.php: -------------------------------------------------------------------------------- 1 | */ 19 | private NonThreadSafeValue $compressor; 20 | 21 | public function __construct( 22 | private string $data, 23 | CompressBatchPromise $promise, 24 | Compressor $compressor, 25 | private int $protocolId 26 | ){ 27 | $this->compressor = new NonThreadSafeValue($compressor); 28 | $this->storeLocal(self::TLS_KEY_PROMISE, $promise); 29 | } 30 | 31 | public function onRun() : void{ 32 | $compressor = $this->compressor->deserialize(); 33 | $protocolAddition = $this->protocolId >= CustomProtocolInfo::PROTOCOL_1_20_60 ? chr($compressor->getNetworkId()) : ''; 34 | $this->setResult($protocolAddition . $compressor->compress($this->data)); 35 | } 36 | 37 | public function onCompletion() : void{ 38 | /** @var CompressBatchPromise $promise */ 39 | $promise = $this->fetchLocal(self::TLS_KEY_PROMISE); 40 | $promise->resolve($this->getResult()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/handlers/CustomSessionStartPacketHandler.php: -------------------------------------------------------------------------------- 1 | getProtocolVersion(); 31 | if(!$this->isCompatibleProtocol($protocolVersion)){ 32 | $this->session->disconnectIncompatibleProtocol($protocolVersion); 33 | 34 | return true; 35 | } 36 | 37 | $this->session->setProtocol($protocolVersion); 38 | 39 | $this->session->sendDataPacket(NetworkSettingsPacket::create( 40 | NetworkSettingsPacket::COMPRESS_EVERYTHING, 41 | $this->session->getCompressor()->getNetworkId(), 42 | false, 43 | 0, 44 | 0 45 | )); 46 | ($this->onSuccess)(); 47 | 48 | return true; 49 | } 50 | 51 | protected function isCompatibleProtocol(int $protocolVersion) : bool{ 52 | return in_array($protocolVersion, CustomProtocolInfo::ACCEPTED_PROTOCOLS, true); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/handlers/static/ItemStackResponseBuilder.php: -------------------------------------------------------------------------------- 1 | > 23 | */ 24 | private array $changedSlots = []; 25 | 26 | public function __construct( 27 | private int $requestId, 28 | private InventoryManager $inventoryManager 29 | ){} 30 | 31 | public function addSlot(int $containerInterfaceId, int $slotId) : void{ 32 | $this->changedSlots[$containerInterfaceId][$slotId] = $slotId; 33 | } 34 | 35 | /** 36 | * @phpstan-return array{Inventory, int} 37 | */ 38 | private function getInventoryAndSlot(int $containerInterfaceId, int $slotId) : ?array{ 39 | [$windowId, $slotId] = ItemStackContainerIdTranslator::translate($containerInterfaceId, $this->inventoryManager->getCurrentWindowId(), $slotId); 40 | $windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId); 41 | if($windowAndSlot === null){ 42 | return null; 43 | } 44 | [$inventory, $slot] = $windowAndSlot; 45 | if(!$inventory->slotExists($slot)){ 46 | return null; 47 | } 48 | 49 | return [$inventory, $slot]; 50 | } 51 | 52 | public function build() : ItemStackResponse{ 53 | $responseInfosByContainer = []; 54 | foreach($this->changedSlots as $containerInterfaceId => $slotIds){ 55 | if($containerInterfaceId === ContainerUIIds::CREATED_OUTPUT){ 56 | continue; 57 | } 58 | foreach($slotIds as $slotId){ 59 | $inventoryAndSlot = $this->getInventoryAndSlot($containerInterfaceId, $slotId); 60 | if($inventoryAndSlot === null){ 61 | //a plugin may have closed the inventory during an event, or the slot may have been invalid 62 | continue; 63 | } 64 | [$inventory, $slot] = $inventoryAndSlot; 65 | 66 | $itemStackInfo = $this->inventoryManager->getItemStackInfo($inventory, $slot); 67 | if($itemStackInfo === null){ 68 | throw new AssumptionFailedError("ItemStackInfo should never be null for an open inventory"); 69 | } 70 | $item = $inventory->getItem($slot); 71 | 72 | $responseInfosByContainer[$containerInterfaceId][] = new ItemStackResponseSlotInfo( 73 | $slotId, 74 | $slotId, 75 | $item->getCount(), 76 | $itemStackInfo->getStackId(), 77 | $item->getCustomName(), 78 | $item->getCustomName(), 79 | $item instanceof Durable ? $item->getDamage() : 0, 80 | ); 81 | } 82 | } 83 | 84 | $responseContainerInfos = []; 85 | foreach($responseInfosByContainer as $containerInterfaceId => $responseInfos){ 86 | $responseContainerInfos[] = new ItemStackResponseContainerInfo(new FullContainerName($containerInterfaceId), $responseInfos); 87 | } 88 | 89 | return new ItemStackResponse(ItemStackResponse::RESULT_OK, $this->requestId, $responseContainerInfos); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/CameraAimAssistPacket.php: -------------------------------------------------------------------------------- 1 | presetId = $presetId; 25 | $result->viewAngle = $viewAngle; 26 | $result->distance = $distance; 27 | $result->targetMode = $targetMode; 28 | $result->actionType = $actionType; 29 | return $result; 30 | } 31 | 32 | public function getPresetId() : string{ return $this->presetId; } 33 | 34 | public function getViewAngle() : Vector2{ return $this->viewAngle; } 35 | 36 | public function getDistance() : float{ return $this->distance; } 37 | 38 | public function getTargetMode() : CameraAimAssistTargetMode{ return $this->targetMode; } 39 | 40 | public function getActionType() : CameraAimAssistActionType{ return $this->actionType; } 41 | 42 | protected function decodePayload(PacketSerializer $in) : void{ 43 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_50) { 44 | $this->presetId = $in->getString(); 45 | } 46 | $this->viewAngle = $in->getVector2(); 47 | $this->distance = $in->getLFloat(); 48 | $this->targetMode = CameraAimAssistTargetMode::fromPacket($in->getByte()); 49 | $this->actionType = CameraAimAssistActionType::fromPacket($in->getByte()); 50 | } 51 | 52 | protected function encodePayload(PacketSerializer $out) : void{ 53 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_50) { 54 | $out->putString($this->presetId); 55 | } 56 | $out->putVector2($this->viewAngle); 57 | $out->putLFloat($this->distance); 58 | $out->putByte($this->targetMode->value); 59 | $out->putByte($this->actionType->value); 60 | } 61 | public function getConstructorArguments(PM_Packet $packet) : array 62 | { 63 | return [ 64 | $packet->getPresetId(), 65 | $packet->getViewAngle(), 66 | $packet->getDistance(), 67 | $packet->getTargetMode(), 68 | $packet->getActionType() 69 | ]; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/CameraAimAssistPresetsPacket.php: -------------------------------------------------------------------------------- 1 | categories = $categories; 25 | $result->presets = $presets; 26 | $result->operation = $operation; 27 | return $result; 28 | } 29 | 30 | protected function decodePayload(PacketSerializer $in) : void{ 31 | $categoriesCount = $in->getUnsignedVarInt(); 32 | while ($categoriesCount-- > 0) { 33 | $this->categories[] = CameraAimAssistCategories::read($in); 34 | } 35 | 36 | $presetsCount = $in->getUnsignedVarInt(); 37 | while ($presetsCount-- > 0) { 38 | $this->presets[] = CameraAimAssistPreset::read($in); 39 | } 40 | 41 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 42 | $this->operation = $in->getByte(); 43 | } 44 | } 45 | protected function encodePayload(PacketSerializer $out) : void{ 46 | $out->putUnsignedVarInt(count($this->categories)); 47 | foreach($this->categories as $category) { 48 | $category->write($out); 49 | } 50 | 51 | $out->putUnsignedVarInt(count($this->presets)); 52 | foreach($this->presets as $preset) { 53 | $preset->write($out); 54 | } 55 | 56 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 57 | $out->putByte($this->operation); 58 | } 59 | } 60 | 61 | public function getConstructorArguments(PM_Packet $packet) : array 62 | { 63 | return [ 64 | $packet->getCategories(), 65 | $packet->getPresets(), 66 | $packet->getOperation() 67 | ]; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/CameraInstructionPacket.php: -------------------------------------------------------------------------------- 1 | set = $set; 29 | $result->clear = $clear; 30 | $result->fade = $fade; 31 | $result->target = $target; 32 | $result->removeTarget = $removeTarget; 33 | return $result; 34 | } 35 | 36 | public function getSet() : ?CameraSetInstruction{ return $this->set; } 37 | 38 | public function getClear() : ?bool{ return $this->clear; } 39 | 40 | public function getFade() : ?CameraFadeInstruction{ return $this->fade; } 41 | 42 | public function getTarget() : ?CameraTargetInstruction{ return $this->target; } 43 | 44 | protected function decodePayload(PacketSerializer $in) : void{ 45 | $this->set = $in->readOptional(fn() => CameraSetInstruction::read($in)); 46 | $this->clear = $in->readOptional($in->getBool(...)); 47 | $this->fade = $in->readOptional(fn() => CameraFadeInstruction::read($in)); 48 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 49 | $this->target = $in->readOptional(fn() => CameraTargetInstruction::read($in)); 50 | $this->removeTarget = $in->readOptional($in->getBool(...)); 51 | } 52 | } 53 | 54 | protected function encodePayload(PacketSerializer $out) : void{ 55 | $out->writeOptional($this->set, fn(CameraSetInstruction $v) => $v->write($out)); 56 | $out->writeOptional($this->clear, $out->putBool(...)); 57 | $out->writeOptional($this->fade, fn(CameraFadeInstruction $v) => $v->write($out)); 58 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 59 | $out->writeOptional($this->target, fn(CameraTargetInstruction $v) => $v->write($out)); 60 | $out->writeOptional($this->removeTarget, $out->putBool(...)); 61 | } 62 | } 63 | 64 | public function getConstructorArguments(PM_Packet $packet) : array 65 | { 66 | return [ 67 | $packet->getSet(), 68 | $packet->getClear(), 69 | $packet->getFade(), 70 | $packet->getTarget() ?? null, 71 | $packet->getRemoveTarget() ?? null 72 | ]; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/CameraPresetsPacket.php: -------------------------------------------------------------------------------- 1 | presets = $presets; 18 | return $result; 19 | } 20 | 21 | public function getPresets() : array{ return $this->presets; } 22 | 23 | protected function decodePayload(PacketSerializer $in) : void{ 24 | $this->presets = []; 25 | for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; $i++){ 26 | $this->presets[] = CustomCameraPreset::read($in); 27 | } 28 | } 29 | 30 | protected function encodePayload(PacketSerializer $out) : void{ 31 | $out->putUnsignedVarInt(count($this->presets)); 32 | foreach($this->presets as $preset){ 33 | $preset->write($out); 34 | 35 | } 36 | } 37 | 38 | public function getConstructorArguments(PM_Packet $packet) : array 39 | { 40 | return [ 41 | $packet->getPresets() 42 | ]; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/ChangeDimensionPacket.php: -------------------------------------------------------------------------------- 1 | dimension = $dimension; 25 | $result->position = $position; 26 | $result->respawn = $respawn; 27 | $result->loadingScreenId = $loadingScreenId; 28 | return $result; 29 | } 30 | 31 | protected function decodePayload(PacketSerializer $in) : void { 32 | $this->dimension = $in->getVarInt(); 33 | $this->position = $in->getVector3(); 34 | $this->respawn = $in->getBool(); 35 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 36 | $this->loadingScreenId = $in->readOptional(fn() => $in->getLInt()); 37 | } 38 | } 39 | 40 | protected function encodePayload(PacketSerializer $out) : void { 41 | $out->putVarInt($this->dimension); 42 | $out->putVector3($this->position); 43 | $out->putBool($this->respawn); 44 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 45 | $out->writeOptional($this->loadingScreenId, $out->putLInt(...)); 46 | } 47 | } 48 | 49 | public function getConstructorArguments(PM_Packet $packet) : array 50 | { 51 | return [ 52 | $packet->dimension, 53 | $packet->position, 54 | $packet->respawn, 55 | $packet->getLoadingScreenId() ?? 0, 56 | ]; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/CodeBuilderSourcePacket.php: -------------------------------------------------------------------------------- 1 | operation = $operation; 27 | $result->category = $category; 28 | $result->value = $value; 29 | $result->codeStatus = $codeStatus; 30 | return $result; 31 | } 32 | 33 | public function getValue() : string{ return $this->value; } 34 | 35 | /** 36 | * @param CustomPacketSerializer $in 37 | */ 38 | protected function decodePayload(PacketSerializer $in) : void{ 39 | $this->operation = $in->getByte(); 40 | $this->category = $in->getByte(); 41 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 42 | $this->codeStatus = $in->getByte(); 43 | }else{ 44 | $this->value = $in->getString(); 45 | } 46 | } 47 | 48 | /** 49 | * @param CustomPacketSerializer $out 50 | */ 51 | protected function encodePayload(PacketSerializer $out) : void{ 52 | $out->putByte($this->operation); 53 | $out->putByte($this->category); 54 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 55 | $out->putByte($this->codeStatus); 56 | }else{ 57 | $out->putString($this->value); 58 | } 59 | } 60 | 61 | public function getConstructorArguments(PM_Packet $packet) : array 62 | { 63 | return [ 64 | $packet->getOperation(), 65 | $packet->getCategory(), 66 | (method_exists($packet, "getCodeStatus") ? $packet->getCodeStatus() : $packet->getValue()) ?? 0, 67 | ]; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/ContainerClosePacket.php: -------------------------------------------------------------------------------- 1 | windowId = $windowId; 26 | $result->windowType = $windowType; 27 | $result->server = $server; 28 | return $result; 29 | } 30 | 31 | /** 32 | * @param CustomPacketSerializer $in 33 | */ 34 | protected function decodePayload(PacketSerializer $in) : void{ 35 | $this->windowId = $in->getByte(); 36 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 37 | $this->windowType = $in->getByte(); 38 | } 39 | $this->server = $in->getBool(); 40 | } 41 | 42 | /** 43 | * @param CustomPacketSerializer $out 44 | */ 45 | protected function encodePayload(PacketSerializer $out) : void 46 | { 47 | $out->putByte($this->windowId); 48 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 49 | $out->putByte($this->windowType); 50 | } 51 | $out->putBool($this->server); 52 | } 53 | 54 | public function getConstructorArguments(PM_Packet $packet) : array 55 | { 56 | return [ 57 | $packet->windowId, 58 | $packet->windowType ?? WindowTypes::CONTAINER, 59 | $packet->server 60 | ]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/CreativeContentPacket.php: -------------------------------------------------------------------------------- 1 | groups = $groups; 29 | $result->items = $items; 30 | return $result; 31 | } 32 | 33 | /** @return CreativeGroupEntry[] */ 34 | public function getGroups() : array{ return $this->groups; } 35 | 36 | /** @return CreativeItemEntry[] */ 37 | public function getItems() : array{ return $this->items; } 38 | 39 | protected function decodePayload(PacketSerializer $in) : void { 40 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 41 | $this->groups = []; 42 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 43 | $this->groups[] = CreativeGroupEntry::read($in); 44 | } 45 | } 46 | 47 | $this->items = []; 48 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 49 | $this->items[] = CreativeItemEntry::read($in); 50 | } 51 | } 52 | 53 | protected function encodePayload(PacketSerializer $out) : void { 54 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 55 | $out->putUnsignedVarInt(count($this->groups)); 56 | foreach($this->groups as $entry){ 57 | $entry->write($out); 58 | } 59 | } 60 | 61 | $out->putUnsignedVarInt(count($this->items)); 62 | foreach($this->items as $entry){ 63 | $entry->write($out); 64 | } 65 | } 66 | 67 | public function getConstructorArguments(PM_Packet $packet) : array { 68 | return [ 69 | $packet->groups, 70 | $packet->items 71 | ]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/DisconnectPacket.php: -------------------------------------------------------------------------------- 1 | reason = $reason; 22 | $result->message = $message; 23 | $result->filteredMessage = $filteredMessage; 24 | return $result; 25 | } 26 | protected function decodePayload(PacketSerializer $in) : void { 27 | $this->reason = $in->getVarInt(); 28 | $skipMessage = $in->getBool(); 29 | $this->message = $skipMessage ? null : $in->getString(); 30 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 31 | $this->filteredMessage = $skipMessage ? null : $in->getString(); 32 | } 33 | } 34 | protected function encodePayload(PacketSerializer $out) : void { 35 | $out->putVarInt($this->reason); 36 | $out->putBool($skipMessage = $this->message === null && $this->filteredMessage === null); 37 | if(!$skipMessage){ 38 | $out->putString($this->message ?? ""); 39 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 40 | $out->putString($this->filteredMessage ?? ""); 41 | } 42 | } 43 | } 44 | public function getConstructorArguments(PM_Packet $packet) : array { 45 | return [ 46 | $packet->reason, 47 | $packet->message, 48 | $packet->filteredMessage ?? "", 49 | ]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/EditorNetworkPacket.php: -------------------------------------------------------------------------------- 1 | isRouteToManager = $isRouteToManager; 23 | $result->payload = $payload; 24 | return $result; 25 | } 26 | protected function decodePayload(PacketSerializer $in) : void { 27 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 28 | $this->isRouteToManager = $in->getBool(); 29 | } 30 | $this->payload = new CacheableNbt($in->getNbtCompoundRoot()); 31 | } 32 | protected function encodePayload(PacketSerializer $out) : void { 33 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 34 | $out->putBool($this->isRouteToManager); 35 | } 36 | $out->put($this->payload->getEncodedNbt()); 37 | } 38 | 39 | public function getConstructorArguments(PM_Packet $packet) : array { 40 | return [ 41 | $packet->isRouteToManager() ?? false, 42 | $packet->getPayload(), 43 | ]; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/EmotePacket.php: -------------------------------------------------------------------------------- 1 | actorRuntimeId = $actorRuntimeId; 27 | $result->emoteId = $emoteId; 28 | $result->emoteLengthTicks = $emoteLengthTicks; 29 | $result->xboxUserId = $xboxUserId; 30 | $result->platformChatId = $platformChatId; 31 | $result->flags = $flags; 32 | return $result; 33 | } 34 | 35 | public function getActorRuntimeId() : int{ 36 | return $this->actorRuntimeId; 37 | } 38 | 39 | public function getEmoteId() : string{ 40 | return $this->emoteId; 41 | } 42 | 43 | public function getEmoteLengthTicks() : int{ return $this->emoteLengthTicks; } 44 | 45 | public function getXboxUserId() : string{ return $this->xboxUserId; } 46 | 47 | public function getPlatformChatId() : string{ return $this->platformChatId; } 48 | 49 | public function getFlags() : int{ 50 | return $this->flags; 51 | } 52 | 53 | protected function decodePayload(PacketSerializer $in) : void { 54 | $this->actorRuntimeId = $in->getActorRuntimeId(); 55 | $this->emoteId = $in->getString(); 56 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30) { 57 | $this->emoteLengthTicks = $in->getUnsignedVarInt(); 58 | } 59 | $this->xboxUserId = $in->getString(); 60 | $this->platformChatId = $in->getString(); 61 | $this->flags = $in->getByte(); 62 | } 63 | protected function encodePayload(PacketSerializer $out) : void { 64 | $out->putActorRuntimeId($this->actorRuntimeId); 65 | $out->putString($this->emoteId); 66 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30) { 67 | $out->putUnsignedVarInt($this->emoteLengthTicks); 68 | } 69 | $out->putString($this->xboxUserId); 70 | $out->putString($this->platformChatId); 71 | $out->putByte($this->flags); 72 | } 73 | public function getConstructorArguments(PM_Packet $packet) : array { 74 | return [ 75 | $packet->getActorRuntimeId(), 76 | $packet->getEmoteId(), 77 | $packet->getEmoteLengthTicks(), 78 | $packet->getXboxUserId(), 79 | $packet->getPlatformChatId(), 80 | $packet->getFlags(), 81 | ]; 82 | } 83 | 84 | public function handle(PacketHandlerInterface $handler) : bool 85 | { 86 | return $handler->handleEmote($this); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/InventoryContentPacket.php: -------------------------------------------------------------------------------- 1 | windowId = $windowId; 28 | $result->items = $items; 29 | $result->customContainerName = $containerName; 30 | $result->dynamicContainerSize = $dynamicContainerSize; 31 | $result->storage = $storage; 32 | return $result; 33 | } 34 | protected function decodePayload(PacketSerializer $in) : void{ 35 | $this->windowId = $in->getUnsignedVarInt(); 36 | $count = $in->getUnsignedVarInt(); 37 | for($i = 0; $i < $count; ++$i){ 38 | $this->items[] = $in->getItemStackWrapper(); 39 | } 40 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 41 | $this->customContainerName = FullContainerName::read($in); 42 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 43 | $this->storage = $in->getItemStackWrapper(); 44 | }else{ 45 | $this->dynamicContainerSize = $in->getUnsignedVarInt(); 46 | } 47 | }elseif($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 48 | $this->customContainerName = new FullContainerName(0, $in->getUnsignedVarInt()); 49 | } 50 | } 51 | 52 | protected function encodePayload(PacketSerializer $out) : void{ 53 | $out->putUnsignedVarInt($this->windowId); 54 | $out->putUnsignedVarInt(count($this->items)); 55 | foreach($this->items as $item){ 56 | $out->putItemStackWrapper($item); 57 | } 58 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 59 | $this->customContainerName->write($out); 60 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 61 | $out->putItemStackWrapper($this->storage); 62 | }else{ 63 | $out->putUnsignedVarInt($this->dynamicContainerSize); 64 | } 65 | }elseif($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 66 | $out->putUnsignedVarInt($this->customContainerName->getDynamicId() ?? 0); 67 | } 68 | } 69 | 70 | public function getConstructorArguments(PM_Packet $packet) : array { 71 | $customContainerName = new FullContainerName($packet->containerName->getContainerId(), $packet->containerName->getDynamicId()); 72 | return [ 73 | $packet->windowId, 74 | $packet->items, 75 | $customContainerName, 76 | 0, 77 | $packet->storage 78 | ]; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/InventorySlotPacket.php: -------------------------------------------------------------------------------- 1 | windowId = $windowId; 28 | $result->inventorySlot = $inventorySlot; 29 | $result->customContainerName = $containerName; 30 | $result->dynamicContainerSize = $dynamicContainerSize; 31 | $result->item = $item; 32 | $result->storage = $storage; 33 | return $result; 34 | } 35 | 36 | protected function decodePayload(PacketSerializer $in) : void{ 37 | $this->windowId = $in->getUnsignedVarInt(); 38 | $this->inventorySlot = $in->getUnsignedVarInt(); 39 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 40 | $this->customContainerName = FullContainerName::read($in); 41 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 42 | $this->storage = $in->getItemStackWrapper(); 43 | }else{ 44 | $this->dynamicContainerSize = $in->getUnsignedVarInt(); 45 | } 46 | }elseif($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 47 | $this->customContainerName = new FullContainerName(0, $in->getUnsignedVarInt()); 48 | } 49 | $this->item = $in->getItemStackWrapper(); 50 | } 51 | 52 | protected function encodePayload(PacketSerializer $out) : void{ 53 | $out->putUnsignedVarInt($this->windowId); 54 | $out->putUnsignedVarInt($this->inventorySlot); 55 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 56 | $this->customContainerName->write($out); 57 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 58 | $out->putItemStackWrapper($this->storage); 59 | }else{ 60 | $out->putUnsignedVarInt($this->dynamicContainerSize); 61 | } 62 | }elseif($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 63 | $out->putUnsignedVarInt($this->customContainerName->getDynamicId() ?? 0); 64 | } 65 | $out->putItemStackWrapper($this->item); 66 | } 67 | public function getConstructorArguments(PM_Packet $packet) : array { 68 | $customContainerName = new FullContainerName($packet->containerName->getContainerId(), $packet->containerName->getDynamicId()); 69 | return [ 70 | $packet->windowId, 71 | $packet->inventorySlot, 72 | $customContainerName, 73 | 0, 74 | $packet->item, 75 | $packet->storage, 76 | ]; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/InventoryTransactionPacket.php: -------------------------------------------------------------------------------- 1 | requestId = $requestId; 31 | $result->requestChangedSlots = $requestChangedSlots; 32 | $result->trData = $trData; 33 | return $result; 34 | } 35 | protected function decodePayload(PacketSerializer $in) : void{ 36 | $this->requestId = $in->readLegacyItemStackRequestId(); 37 | $this->requestChangedSlots = []; 38 | if($this->requestId !== 0){ 39 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 40 | $this->requestChangedSlots[] = InventoryTransactionChangedSlotsHack::read($in); 41 | } 42 | } 43 | 44 | $transactionType = $in->getUnsignedVarInt(); 45 | 46 | $this->trData = match($transactionType){ 47 | NormalTransactionData::ID => new NormalTransactionData(), 48 | MismatchTransactionData::ID => new MismatchTransactionData(), 49 | UseItemTransactionData::ID => new CustomUseItemTransactionData(), 50 | UseItemOnEntityTransactionData::ID => new UseItemOnEntityTransactionData(), 51 | ReleaseItemTransactionData::ID => new ReleaseItemTransactionData(), 52 | default => throw new PacketDecodeException("Unknown transaction type $transactionType"), 53 | }; 54 | 55 | $this->trData->decode($in); 56 | } 57 | 58 | protected function encodePayload(PacketSerializer $out) : void{ 59 | $out->writeLegacyItemStackRequestId($this->requestId); 60 | if($this->requestId !== 0){ 61 | $out->putUnsignedVarInt(count($this->requestChangedSlots)); 62 | foreach($this->requestChangedSlots as $changedSlots){ 63 | $changedSlots->write($out); 64 | } 65 | } 66 | 67 | $out->putUnsignedVarInt($this->trData->getTypeId()); 68 | 69 | $this->trData->encode($out); 70 | } 71 | public function getConstructorArguments(PM_Packet $packet) : array { 72 | return [ 73 | $packet->requestId, 74 | $packet->requestChangedSlots, 75 | $packet->trData, 76 | ]; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/ItemRegistryPacket.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | private array $entries; 22 | 23 | /** 24 | * @generate-create-func 25 | * @param ItemTypeEntry[] $entries 26 | * @phpstan-param list $entries 27 | */ 28 | public static function createPacket(array $entries) : self{ 29 | $result = new self(); 30 | $result->entries = $entries; 31 | return $result; 32 | } 33 | 34 | /** 35 | * @return ItemTypeEntry[] 36 | * @phpstan-return list 37 | */ 38 | public function getEntries() : array{ return $this->entries; } 39 | 40 | protected function decodePayload(PacketSerializer $in) : void{ 41 | $this->entries = []; 42 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 43 | $stringId = $in->getString(); 44 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 45 | $numericId = $in->getSignedLShort(); 46 | $isComponentBased = $in->getBool(); 47 | $version = $in->getVarInt(); 48 | } 49 | $nbt = $in->getNbtCompoundRoot(); 50 | $this->entries[] = new ItemTypeEntry($stringId, $numericId ?? -1, $isComponentBased ?? false, $version ?? -1, new CacheableNbt($nbt)); 51 | } 52 | } 53 | 54 | protected function encodePayload(PacketSerializer $out) : void{ 55 | $out->putUnsignedVarInt(count($this->entries)); 56 | foreach($this->entries as $entry){ 57 | $out->putString($entry->getStringId()); 58 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 59 | $out->putLShort($entry->getNumericId()); 60 | $out->putBool($entry->isComponentBased()); 61 | $out->putVarInt($entry->getVersion()); 62 | } 63 | $out->put($entry->getComponentNbt()->getEncodedNbt()); 64 | } 65 | } 66 | 67 | public function getConstructorArguments(PM_Packet $packet) : array { 68 | return [ 69 | $packet->entries 70 | ]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/ItemStackRequestPacket.php: -------------------------------------------------------------------------------- 1 | requests = $requests; 24 | return $result; 25 | } 26 | 27 | /** @return CustomItemStackRequest[] */ 28 | public function getRequests() : array{ return $this->requests; } 29 | 30 | protected function decodePayload(PacketSerializer $in) : void { 31 | $this->requests = []; 32 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 33 | $this->requests[] = CustomItemStackRequest::read($in); 34 | } 35 | } 36 | protected function encodePayload(PacketSerializer $out) : void { 37 | $out->putUnsignedVarInt(count($this->requests)); 38 | foreach($this->requests as $request){ 39 | $request->write($out); 40 | } 41 | } 42 | 43 | public function getConstructorArguments(PM_Packet $packet) : array { 44 | return [ 45 | $packet->getRequests(), 46 | ]; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/ItemStackResponsePacket.php: -------------------------------------------------------------------------------- 1 | responses = $responses; 24 | return $result; 25 | } 26 | 27 | /** @return ItemStackResponse[] */ 28 | public function getResponses() : array{ return $this->responses; } 29 | 30 | protected function decodePayload(PacketSerializer $in) : void{ 31 | $this->responses = []; 32 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 33 | $this->responses[] = ItemStackResponse::read($in); 34 | } 35 | } 36 | 37 | protected function encodePayload(PacketSerializer $out) : void{ 38 | $out->putUnsignedVarInt(count($this->responses)); 39 | foreach($this->responses as $response){ 40 | $response->write($out); 41 | } 42 | } 43 | 44 | public function getConstructorArguments(PM_Packet $packet) : array { 45 | return [ 46 | $packet->getResponses(), 47 | ]; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/LecternUpdatePacket.php: -------------------------------------------------------------------------------- 1 | page = $page; 25 | $result->totalPages = $totalPages; 26 | $result->blockPosition = $blockPosition; 27 | $result->dropBook = $dropBook; 28 | return $result; 29 | } 30 | 31 | protected function decodePayload(PacketSerializer $in) : void{ 32 | $this->page = $in->getByte(); 33 | $this->totalPages = $in->getByte(); 34 | $this->blockPosition = $in->getBlockPosition(); 35 | if($in->getProtocol() <= CustomProtocolInfo::PROTOCOL_1_20_60){ 36 | $this->dropBook = $in->getBool(); 37 | } 38 | } 39 | 40 | protected function encodePayload(PacketSerializer $out) : void{ 41 | $out->putByte($this->page); 42 | $out->putByte($this->totalPages); 43 | $out->putBlockPosition($this->blockPosition); 44 | if($out->getProtocol() <= CustomProtocolInfo::PROTOCOL_1_20_60){ 45 | $out->putBool($this->dropBook); 46 | } 47 | } 48 | 49 | public function getConstructorArguments(PM_Packet $packet) : array 50 | { 51 | return [ 52 | $packet->page, 53 | $packet->totalPages, 54 | $packet->blockPosition, 55 | $this->dropBook ?? false 56 | ]; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/LevelChunkPacket.php: -------------------------------------------------------------------------------- 1 | chunkPosition = $chunkPosition; 46 | $result->dimensionId = $dimensionId; 47 | $result->subChunkCount = $subChunkCount; 48 | $result->clientSubChunkRequestsEnabled = $clientSubChunkRequestsEnabled; 49 | $result->usedBlobHashes = $usedBlobHashes; 50 | $result->extraPayload = $extraPayload; 51 | return $result; 52 | } 53 | protected function decodePayload(PacketSerializer $in) : void { 54 | $this->chunkPosition = ChunkPosition::read($in); 55 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_60) { 56 | $this->dimensionId = $in->getVarInt(); 57 | } 58 | 59 | $subChunkCountButNotReally = $in->getUnsignedVarInt(); 60 | if($subChunkCountButNotReally === self::CLIENT_REQUEST_FULL_COLUMN_FAKE_COUNT){ 61 | $this->clientSubChunkRequestsEnabled = true; 62 | $this->subChunkCount = PHP_INT_MAX; 63 | }elseif($subChunkCountButNotReally === self::CLIENT_REQUEST_TRUNCATED_COLUMN_FAKE_COUNT){ 64 | $this->clientSubChunkRequestsEnabled = true; 65 | $this->subChunkCount = $in->getLShort(); 66 | }else{ 67 | $this->clientSubChunkRequestsEnabled = false; 68 | $this->subChunkCount = $subChunkCountButNotReally; 69 | } 70 | 71 | $cacheEnabled = $in->getBool(); 72 | if($cacheEnabled){ 73 | $this->usedBlobHashes = []; 74 | $count = $in->getUnsignedVarInt(); 75 | if($count > self::MAX_BLOB_HASHES){ 76 | throw new PacketDecodeException("Expected at most " . self::MAX_BLOB_HASHES . " blob hashes, got " . $count); 77 | } 78 | for($i = 0; $i < $count; ++$i){ 79 | $this->usedBlobHashes[] = $in->getLLong(); 80 | } 81 | } 82 | $this->extraPayload = $in->getString(); 83 | } 84 | protected function encodePayload(PacketSerializer $out) : void { 85 | $this->chunkPosition->write($out); 86 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_60) { 87 | $out->putVarInt($this->dimensionId); 88 | } 89 | 90 | if($this->clientSubChunkRequestsEnabled){ 91 | if($this->subChunkCount === PHP_INT_MAX){ 92 | $out->putUnsignedVarInt(self::CLIENT_REQUEST_FULL_COLUMN_FAKE_COUNT); 93 | }else{ 94 | $out->putUnsignedVarInt(self::CLIENT_REQUEST_TRUNCATED_COLUMN_FAKE_COUNT); 95 | $out->putLShort($this->subChunkCount); 96 | } 97 | }else{ 98 | $out->putUnsignedVarInt($this->subChunkCount); 99 | } 100 | 101 | $out->putBool($this->usedBlobHashes !== null); 102 | if($this->usedBlobHashes !== null){ 103 | $out->putUnsignedVarInt(count($this->usedBlobHashes)); 104 | foreach($this->usedBlobHashes as $hash){ 105 | $out->putLLong($hash); 106 | } 107 | } 108 | $out->putString($this->extraPayload); 109 | } 110 | public function getConstructorArguments(PM_Packet $packet) : array { 111 | return [ 112 | $packet->getChunkPosition(), 113 | $packet->getDimensionId() ?? 0, 114 | $packet->getSubChunkCount(), 115 | $packet->isClientSubChunkRequestEnabled(), 116 | $packet->getUsedBlobHashes(), 117 | $packet->getExtraPayload(), 118 | ]; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/LevelSoundEventPacket.php: -------------------------------------------------------------------------------- 1 | sound = $sound; 32 | $result->position = $position; 33 | $result->extraData = $extraData; 34 | $result->entityType = $entityType; 35 | $result->isBabyMob = $isBabyMob; 36 | $result->disableRelativeVolume = $disableRelativeVolume; 37 | $result->actorUniqueId = $actorUniqueId; 38 | return $result; 39 | } 40 | 41 | public static function nonActorSound(int $sound, Vector3 $position, bool $disableRelativeVolume, int $extraData = -1) : self{ 42 | return self::createPacket($sound, $position, $extraData, ":", false, $disableRelativeVolume, -1); 43 | } 44 | 45 | protected function decodePayload(PacketSerializer $in) : void{ 46 | $this->sound = $in->getUnsignedVarInt(); 47 | $this->position = $in->getVector3(); 48 | $this->extraData = $in->getVarInt(); 49 | $this->entityType = $in->getString(); 50 | $this->isBabyMob = $in->getBool(); 51 | $this->disableRelativeVolume = $in->getBool(); 52 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_70){ 53 | $this->actorUniqueId = $in->getLLong(); //WHY IS THIS NON-STANDARD? 54 | } 55 | } 56 | 57 | protected function encodePayload(PacketSerializer $out) : void{ 58 | $out->putUnsignedVarInt($this->sound); 59 | $out->putVector3($this->position); 60 | $out->putVarInt($this->extraData); 61 | $out->putString($this->entityType); 62 | $out->putBool($this->isBabyMob); 63 | $out->putBool($this->disableRelativeVolume); 64 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_70){ 65 | $out->putLLong($this->actorUniqueId); 66 | } 67 | } 68 | 69 | public function getConstructorArguments(PM_Packet $packet) : array 70 | { 71 | return [ 72 | $packet->sound, 73 | $packet->position, 74 | $packet->extraData, 75 | $packet->entityType, 76 | $packet->isBabyMob, 77 | $packet->disableRelativeVolume, 78 | $packet->actorUniqueId 79 | ]; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/MobArmorEquipmentPacket.php: -------------------------------------------------------------------------------- 1 | actorRuntimeId = $actorRuntimeId; 27 | $result->head = $head; 28 | $result->chest = $chest; 29 | $result->legs = $legs; 30 | $result->feet = $feet; 31 | $result->body = $body; 32 | return $result; 33 | } 34 | protected function decodePayload(PacketSerializer $in) : void { 35 | $this->actorRuntimeId = $in->getActorRuntimeId(); 36 | $this->head = $in->getItemStackWrapper(); 37 | $this->chest = $in->getItemStackWrapper(); 38 | $this->legs = $in->getItemStackWrapper(); 39 | $this->feet = $in->getItemStackWrapper(); 40 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 41 | $this->body = $in->getItemStackWrapper(); 42 | } 43 | } 44 | protected function encodePayload(PacketSerializer $out) : void { 45 | $out->putActorRuntimeId($this->actorRuntimeId); 46 | $out->putItemStackWrapper($this->head); 47 | $out->putItemStackWrapper($this->chest); 48 | $out->putItemStackWrapper($this->legs); 49 | $out->putItemStackWrapper($this->feet); 50 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 51 | $out->putItemStackWrapper($this->body); 52 | } 53 | } 54 | 55 | public function getConstructorArguments(PM_Packet $packet) : array { 56 | return [ 57 | $packet->actorRuntimeId, 58 | $packet->head, 59 | $packet->chest, 60 | $packet->legs, 61 | $packet->feet, 62 | $packet->body ?? new ItemStackWrapper(0, ItemStack::null()) 63 | ]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/MobEffectPacket.php: -------------------------------------------------------------------------------- 1 | actorRuntimeId = $actorRuntimeId; 35 | $result->eventId = $eventId; 36 | $result->effectId = $effectId; 37 | $result->amplifier = $amplifier; 38 | $result->particles = $particles; 39 | $result->duration = $duration; 40 | $result->tick = $tick; 41 | return $result; 42 | } 43 | 44 | protected function decodePayload(PacketSerializer $in) : void{ 45 | $this->actorRuntimeId = $in->getActorRuntimeId(); 46 | $this->eventId = $in->getByte(); 47 | $this->effectId = $in->getVarInt(); 48 | $this->amplifier = $in->getVarInt(); 49 | $this->particles = $in->getBool(); 50 | $this->duration = $in->getVarInt(); 51 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 52 | $this->tick = $in->getUnsignedVarLong(); 53 | }elseif($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_70){ 54 | $this->tick = $in->getLLong(); 55 | } 56 | } 57 | 58 | protected function encodePayload(PacketSerializer $out) : void{ 59 | $out->putActorRuntimeId($this->actorRuntimeId); 60 | $out->putByte($this->eventId); 61 | $out->putVarInt($this->effectId); 62 | $out->putVarInt($this->amplifier); 63 | $out->putBool($this->particles); 64 | $out->putVarInt($this->duration); 65 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 66 | $out->putUnsignedVarLong($this->tick); 67 | }elseif($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_70){ 68 | $out->putLLong($this->tick); 69 | } 70 | } 71 | 72 | public function getConstructorArguments(PM_Packet $packet) : array 73 | { 74 | return [ 75 | $packet->actorRuntimeId, 76 | $packet->eventId, 77 | $packet->effectId, 78 | $packet->amplifier, 79 | $packet->particles, 80 | $packet->duration, 81 | $packet->tick ?? 0 82 | ]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/PlayerArmorDamagePacket.php: -------------------------------------------------------------------------------- 1 | headSlotDamage = $headSlotDamage; 32 | $result->chestSlotDamage = $chestSlotDamage; 33 | $result->legsSlotDamage = $legsSlotDamage; 34 | $result->feetSlotDamage = $feetSlotDamage; 35 | $result->bodySlotDamage = $bodySlotDamage; 36 | return $result; 37 | } 38 | 39 | public function getHeadSlotDamage() : ?int{ return $this->headSlotDamage; } 40 | 41 | public function getChestSlotDamage() : ?int{ return $this->chestSlotDamage; } 42 | 43 | public function getLegsSlotDamage() : ?int{ return $this->legsSlotDamage; } 44 | 45 | public function getFeetSlotDamage() : ?int{ return $this->feetSlotDamage; } 46 | 47 | public function getBodySlotDamage() : ?int{ return $this->bodySlotDamage; } 48 | 49 | private function maybeReadDamage(int $flags, int $flag, PacketSerializer $in) : ?int{ 50 | if(($flags & (1 << $flag)) !== 0){ 51 | return $in->getVarInt(); 52 | } 53 | return null; 54 | } 55 | 56 | protected function decodePayload(PacketSerializer $in) : void{ 57 | $flags = $in->getByte(); 58 | 59 | $this->headSlotDamage = $this->maybeReadDamage($flags, self::FLAG_HEAD, $in); 60 | $this->chestSlotDamage = $this->maybeReadDamage($flags, self::FLAG_CHEST, $in); 61 | $this->legsSlotDamage = $this->maybeReadDamage($flags, self::FLAG_LEGS, $in); 62 | $this->feetSlotDamage = $this->maybeReadDamage($flags, self::FLAG_FEET, $in); 63 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 64 | $this->bodySlotDamage = $this->maybeReadDamage($flags, self::FLAG_BODY, $in); 65 | } 66 | } 67 | 68 | private function composeFlag(?int $field, int $flag) : int{ 69 | return $field !== null ? (1 << $flag) : 0; 70 | } 71 | 72 | private function maybeWriteDamage(?int $field, PacketSerializer $out) : void{ 73 | if($field !== null){ 74 | $out->putVarInt($field); 75 | } 76 | } 77 | 78 | /** 79 | * @param CustomPacketSerializer $out 80 | */ 81 | protected function encodePayload(PacketSerializer $out) : void{ 82 | $out->putByte( 83 | $this->composeFlag($this->headSlotDamage, self::FLAG_HEAD) | 84 | $this->composeFlag($this->chestSlotDamage, self::FLAG_CHEST) | 85 | $this->composeFlag($this->legsSlotDamage, self::FLAG_LEGS) | 86 | $this->composeFlag($this->feetSlotDamage, self::FLAG_FEET) | 87 | ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20 ? $this->composeFlag($this->bodySlotDamage, self::FLAG_BODY) : 0) 88 | ); 89 | 90 | $this->maybeWriteDamage($this->headSlotDamage, $out); 91 | $this->maybeWriteDamage($this->chestSlotDamage, $out); 92 | $this->maybeWriteDamage($this->legsSlotDamage, $out); 93 | $this->maybeWriteDamage($this->feetSlotDamage, $out); 94 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 95 | $this->maybeWriteDamage($this->bodySlotDamage, $out); 96 | } 97 | } 98 | 99 | public function getConstructorArguments(PM_Packet $packet) : array 100 | { 101 | return [ 102 | $packet->getHeadSlotDamage(), 103 | $packet->getChestSlotDamage(), 104 | $packet->getLegsSlotDamage(), 105 | $packet->getFeetSlotDamage(), 106 | $packet->getBodySlotDamage() ?? null 107 | ]; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/PlayerAuthInputVehicleInfo.php: -------------------------------------------------------------------------------- 1 | vehicleRotationX; } 19 | 20 | public function getVehicleRotationZ() : ?float{ return $this->vehicleRotationZ; } 21 | 22 | public function getPredictedVehicleActorUniqueId() : int{ return $this->predictedVehicleActorUniqueId; } 23 | 24 | public static function read(PacketSerializer $in) : self{ 25 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_70){ 26 | $vehicleRotationX = $in->getLFloat(); 27 | $vehicleRotationZ = $in->getLFloat(); 28 | } 29 | $predictedVehicleActorUniqueId = $in->getActorUniqueId(); 30 | 31 | return new self($vehicleRotationX ?? null, $vehicleRotationZ ?? null, $predictedVehicleActorUniqueId); 32 | } 33 | 34 | public function write(PacketSerializer $out) : void{ 35 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_70){ 36 | $out->putLFloat($this->vehicleRotationX ?? throw new \InvalidArgumentException("vehicleRotationX must be set for 1.20.70+")); 37 | $out->putLFloat($this->vehicleRotationZ ?? throw new \InvalidArgumentException("vehicleRotationZ must be set for 1.20.70+")); 38 | } 39 | $out->putActorUniqueId($this->predictedVehicleActorUniqueId); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/PlayerListPacket.php: -------------------------------------------------------------------------------- 1 | type = $type; 28 | $result->entries = $entries; 29 | return $result; 30 | } 31 | protected function decodePayload(PacketSerializer $in) : void { 32 | $this->type = $in->getByte(); 33 | $count = $in->getUnsignedVarInt(); 34 | for($i = 0; $i < $count; ++$i){ 35 | $entry = new PlayerListEntry(); 36 | 37 | $entry->uuid = $in->getUUID(); 38 | if($this->type === self::TYPE_ADD){ 39 | $entry->actorUniqueId = $in->getActorUniqueId(); 40 | $entry->username = $in->getString(); 41 | $entry->xboxUserId = $in->getString(); 42 | $entry->platformChatId = $in->getString(); 43 | $entry->buildPlatform = $in->getLInt(); 44 | $entry->skinData = $in->getSkin(); 45 | $entry->isTeacher = $in->getBool(); 46 | $entry->isHost = $in->getBool(); 47 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_60) { 48 | $entry->isSubClient = $in->getBool(); 49 | } 50 | } 51 | 52 | $this->entries[$i] = $entry; 53 | } 54 | if($this->type === self::TYPE_ADD){ 55 | for($i = 0; $i < $count; ++$i){ 56 | $this->entries[$i]->skinData->setVerified($in->getBool()); 57 | } 58 | } 59 | } 60 | protected function encodePayload(PacketSerializer $out) : void { 61 | $out->putByte($this->type); 62 | $out->putUnsignedVarInt(count($this->entries)); 63 | foreach($this->entries as $entry){ 64 | if($this->type === self::TYPE_ADD){ 65 | $out->putUUID($entry->uuid); 66 | $out->putActorUniqueId($entry->actorUniqueId); 67 | $out->putString($entry->username); 68 | $out->putString($entry->xboxUserId); 69 | $out->putString($entry->platformChatId); 70 | $out->putLInt($entry->buildPlatform); 71 | $out->putSkin($entry->skinData); 72 | $out->putBool($entry->isTeacher); 73 | $out->putBool($entry->isHost); 74 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_60) { 75 | $out->putBool($entry->isSubClient); 76 | } 77 | }else{ 78 | $out->putUUID($entry->uuid); 79 | } 80 | } 81 | if($this->type === self::TYPE_ADD){ 82 | foreach($this->entries as $entry){ 83 | $out->putBool($entry->skinData->isVerified()); 84 | } 85 | } 86 | } 87 | public function getConstructorArguments(PM_Packet $packet) : array { 88 | return [ 89 | $packet->type, 90 | $packet->entries 91 | ]; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/ResourcePackStackPacket.php: -------------------------------------------------------------------------------- 1 | resourcePackStack = $resourcePackStack; 34 | $result->behaviorPackStack = $behaviorPackStack; 35 | $result->mustAccept = $mustAccept; 36 | $result->baseGameVersion = $baseGameVersion; 37 | $result->experiments = $experiments; 38 | $result->useVanillaEditorPacks = $useVanillaEditorPacks; 39 | return $result; 40 | } 41 | 42 | protected function decodePayload(PacketSerializer $in) : void{ 43 | $this->mustAccept = $in->getBool(); 44 | $behaviorPackCount = $in->getUnsignedVarInt(); 45 | while($behaviorPackCount-- > 0){ 46 | $this->behaviorPackStack[] = ResourcePackStackEntry::read($in); 47 | } 48 | 49 | $resourcePackCount = $in->getUnsignedVarInt(); 50 | while($resourcePackCount-- > 0){ 51 | $this->resourcePackStack[] = ResourcePackStackEntry::read($in); 52 | } 53 | 54 | $this->baseGameVersion = $in->getString(); 55 | $this->experiments = Experiments::read($in); 56 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_80){ 57 | $this->useVanillaEditorPacks = $in->getBool(); 58 | } 59 | } 60 | 61 | protected function encodePayload(PacketSerializer $out) : void{ 62 | $out->putBool($this->mustAccept); 63 | 64 | $out->putUnsignedVarInt(count($this->behaviorPackStack)); 65 | foreach($this->behaviorPackStack as $entry){ 66 | $entry->write($out); 67 | } 68 | 69 | $out->putUnsignedVarInt(count($this->resourcePackStack)); 70 | foreach($this->resourcePackStack as $entry){ 71 | $entry->write($out); 72 | } 73 | 74 | $out->putString($this->baseGameVersion); 75 | $this->experiments->write($out); 76 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_80) { 77 | $out->putBool($this->useVanillaEditorPacks); 78 | } 79 | } 80 | 81 | public function getConstructorArguments(PM_Packet $packet) : array 82 | { 83 | return [ 84 | $packet->resourcePackStack, 85 | $packet->behaviorPackStack, 86 | $packet->mustAccept, 87 | $packet->baseGameVersion, 88 | $packet->experiments, 89 | $packet->useVanillaEditorPacks ?? false 90 | ]; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/SetActorMotionPacket.php: -------------------------------------------------------------------------------- 1 | actorRuntimeId = $actorRuntimeId; 24 | $result->motion = $motion; 25 | $result->tick = $tick; 26 | return $result; 27 | } 28 | 29 | protected function decodePayload(PacketSerializer $in) : void{ 30 | $this->actorRuntimeId = $in->getActorRuntimeId(); 31 | $this->motion = $in->getVector3(); 32 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_70){ 33 | $this->tick = $in->getUnsignedVarLong(); 34 | } 35 | } 36 | 37 | protected function encodePayload(PacketSerializer $out) : void{ 38 | $out->putActorRuntimeId($this->actorRuntimeId); 39 | $out->putVector3($this->motion); 40 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_70) { 41 | $out->putUnsignedVarLong($this->tick); 42 | } 43 | } 44 | 45 | public function getConstructorArguments(PM_Packet $packet) : array 46 | { 47 | return [ 48 | $packet->actorRuntimeId, 49 | $packet->motion, 50 | $packet->tick ?? 0 51 | ]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/SetHudPacket.php: -------------------------------------------------------------------------------- 1 | hudElements = $hudElements; 22 | $result->visibility = $visibility; 23 | return $result; 24 | } 25 | 26 | public function getHudElements() : array{ return $this->hudElements; } 27 | 28 | public function getVisibility() : HudVisibility{ return $this->visibility; } 29 | 30 | protected function decodePayload(PacketSerializer $in) : void{ 31 | $this->hudElements = []; 32 | for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; ++$i){ 33 | $this->hudElements[] = HudElement::fromPacket($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_70 ? $in->getVarInt() : $in->getByte()); 34 | } 35 | $this->visibility = HudVisibility::fromPacket($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_70 ? $in->getVarInt() : $in->getByte()); 36 | } 37 | 38 | protected function encodePayload(PacketSerializer $out) : void{ 39 | $out->putUnsignedVarInt(count($this->hudElements)); 40 | foreach($this->hudElements as $element){ 41 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_70){ 42 | $out->putVarInt($element->value); 43 | }else{ 44 | $out->putByte($element->value); 45 | } 46 | } 47 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_70){ 48 | $out->putVarInt($this->visibility->value); 49 | }else{ 50 | $out->putByte($this->visibility->value); 51 | } 52 | } 53 | 54 | public function getConstructorArguments(PM_Packet $packet) : array 55 | { 56 | return [ 57 | $packet->getHudElements(), 58 | $packet->getVisibility() 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/SetTitlePacket.php: -------------------------------------------------------------------------------- 1 | type = $type; 37 | $result->text = $text; 38 | $result->fadeInTime = $fadeInTime; 39 | $result->stayTime = $stayTime; 40 | $result->fadeOutTime = $fadeOutTime; 41 | $result->xuid = $xuid; 42 | $result->platformOnlineId = $platformOnlineId; 43 | $result->filteredTitleText = $filteredTitleText; 44 | return $result; 45 | } 46 | 47 | protected function decodePayload(PacketSerializer $in) : void { 48 | $this->type = $in->getVarInt(); 49 | $this->text = $in->getString(); 50 | $this->fadeInTime = $in->getVarInt(); 51 | $this->stayTime = $in->getVarInt(); 52 | $this->fadeOutTime = $in->getVarInt(); 53 | $this->xuid = $in->getString(); 54 | $this->platformOnlineId = $in->getString(); 55 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 56 | $this->filteredTitleText = $in->getString(); 57 | } 58 | } 59 | protected function encodePayload(PacketSerializer $out) : void { 60 | $out->putVarInt($this->type); 61 | $out->putString($this->text); 62 | $out->putVarInt($this->fadeInTime); 63 | $out->putVarInt($this->stayTime); 64 | $out->putVarInt($this->fadeOutTime); 65 | $out->putString($this->xuid); 66 | $out->putString($this->platformOnlineId); 67 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 68 | $out->putString($this->filteredTitleText); 69 | } 70 | } 71 | public function getConstructorArguments(PM_Packet $packet) : array { 72 | return [ 73 | $packet->type, 74 | $packet->text, 75 | $packet->fadeInTime, 76 | $packet->stayTime, 77 | $packet->fadeOutTime, 78 | $packet->xuid, 79 | $packet->platformOnlineId, 80 | $packet->filteredTitleText ?? false, 81 | ]; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/StopSoundPacket.php: -------------------------------------------------------------------------------- 1 | soundName = $soundName; 22 | $result->stopAll = $stopAll; 23 | $result->stopLegacyMusic = $stopLegacyMusic; 24 | return $result; 25 | } 26 | protected function decodePayload(PacketSerializer $in) : void { 27 | $this->soundName = $in->getString(); 28 | $this->stopAll = $in->getBool(); 29 | if ($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 30 | $this->stopLegacyMusic = $in->getBool(); 31 | } 32 | } 33 | protected function encodePayload(PacketSerializer $out) : void { 34 | $out->putString($this->soundName); 35 | $out->putBool($this->stopAll); 36 | if ($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 37 | $out->putBool($this->stopLegacyMusic); 38 | } 39 | } 40 | public function getConstructorArguments(PM_Packet $packet) : array { 41 | return [ 42 | $packet->soundName, 43 | $packet->stopAll, 44 | $packet->stopLegacyMusic ?? false, 45 | ]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/TextPacket.php: -------------------------------------------------------------------------------- 1 | type = $type; 42 | $result->message = $message; 43 | return $result; 44 | } 45 | 46 | /** 47 | * @param string[] $parameters 48 | */ 49 | private static function baseTranslation(int $type, string $key, array $parameters) : self{ 50 | $result = new self(); 51 | $result->type = $type; 52 | $result->needsTranslation = true; 53 | $result->message = $key; 54 | $result->parameters = $parameters; 55 | return $result; 56 | } 57 | 58 | public static function raw(string $message) : self{ 59 | return self::messageOnly(self::TYPE_RAW, $message); 60 | } 61 | 62 | /** 63 | * @param string[] $parameters 64 | */ 65 | public static function translation(string $key, array $parameters = []) : self{ 66 | return self::baseTranslation(self::TYPE_TRANSLATION, $key, $parameters); 67 | } 68 | 69 | public static function popup(string $message) : self{ 70 | return self::messageOnly(self::TYPE_POPUP, $message); 71 | } 72 | 73 | /** 74 | * @param string[] $parameters 75 | */ 76 | public static function translatedPopup(string $key, array $parameters = []) : self{ 77 | return self::baseTranslation(self::TYPE_POPUP, $key, $parameters); 78 | } 79 | 80 | /** 81 | * @param string[] $parameters 82 | */ 83 | public static function jukeboxPopup(string $key, array $parameters = []) : self{ 84 | return self::baseTranslation(self::TYPE_JUKEBOX_POPUP, $key, $parameters); 85 | } 86 | 87 | public static function tip(string $message) : self{ 88 | return self::messageOnly(self::TYPE_TIP, $message); 89 | } 90 | 91 | /** 92 | * @param CustomPacketSerializer $in 93 | */ 94 | protected function decodePayload(PacketSerializer $in) : void{ 95 | $this->type = $in->getByte(); 96 | $this->needsTranslation = $in->getBool(); 97 | switch($this->type){ 98 | case self::TYPE_CHAT: 99 | case self::TYPE_WHISPER: 100 | /** @noinspection PhpMissingBreakStatementInspection */ 101 | case self::TYPE_ANNOUNCEMENT: 102 | $this->sourceName = $in->getString(); 103 | case self::TYPE_RAW: 104 | case self::TYPE_TIP: 105 | case self::TYPE_SYSTEM: 106 | case self::TYPE_JSON_WHISPER: 107 | case self::TYPE_JSON: 108 | case self::TYPE_JSON_ANNOUNCEMENT: 109 | $this->message = $in->getString(); 110 | break; 111 | 112 | case self::TYPE_TRANSLATION: 113 | case self::TYPE_POPUP: 114 | case self::TYPE_JUKEBOX_POPUP: 115 | $this->message = $in->getString(); 116 | $count = $in->getUnsignedVarInt(); 117 | for($i = 0; $i < $count; ++$i){ 118 | $this->parameters[] = $in->getString(); 119 | } 120 | break; 121 | } 122 | 123 | $this->xboxUserId = $in->getString(); 124 | $this->platformChatId = $in->getString(); 125 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0) { 126 | $this->filteredMessage = $in->getString(); 127 | } 128 | } 129 | 130 | /** 131 | * @param CustomPacketSerializer $out 132 | */ 133 | protected function encodePayload(PacketSerializer $out) : void{ 134 | $out->putByte($this->type); 135 | $out->putBool($this->needsTranslation); 136 | switch($this->type){ 137 | case self::TYPE_CHAT: 138 | case self::TYPE_WHISPER: 139 | /** @noinspection PhpMissingBreakStatementInspection */ 140 | case self::TYPE_ANNOUNCEMENT: 141 | $out->putString($this->sourceName); 142 | case self::TYPE_RAW: 143 | case self::TYPE_TIP: 144 | case self::TYPE_SYSTEM: 145 | case self::TYPE_JSON_WHISPER: 146 | case self::TYPE_JSON: 147 | case self::TYPE_JSON_ANNOUNCEMENT: 148 | $out->putString($this->message); 149 | break; 150 | 151 | case self::TYPE_TRANSLATION: 152 | case self::TYPE_POPUP: 153 | case self::TYPE_JUKEBOX_POPUP: 154 | $out->putString($this->message); 155 | $out->putUnsignedVarInt(count($this->parameters)); 156 | foreach($this->parameters as $p){ 157 | $out->putString($p); 158 | } 159 | break; 160 | } 161 | 162 | $out->putString($this->xboxUserId); 163 | $out->putString($this->platformChatId); 164 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0) { 165 | $out->putString($this->filteredMessage); 166 | } 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/TickSyncPacket.php: -------------------------------------------------------------------------------- 1 | clientSendTime = $clientSendTime; 23 | $result->serverReceiveTime = $serverReceiveTime; 24 | return $result; 25 | } 26 | 27 | public static function request(int $clientTime) : self{ 28 | return self::create($clientTime, 0 /* useless, but always written anyway */); 29 | } 30 | 31 | public static function response(int $clientSendTime, int $serverReceiveTime) : self{ 32 | return self::create($clientSendTime, $serverReceiveTime); 33 | } 34 | 35 | protected function decodePayload(PacketSerializer $in) : void{ 36 | $this->clientSendTime = $in->getLLong(); 37 | $this->serverReceiveTime = $in->getLLong(); 38 | } 39 | 40 | protected function encodePayload(PacketSerializer $out) : void{ 41 | $out->putLLong($this->clientSendTime); 42 | $out->putLLong($this->serverReceiveTime); 43 | } 44 | 45 | public function handle(PacketHandlerInterface $handler) : bool{ 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/TransferPacket.php: -------------------------------------------------------------------------------- 1 | address = $address; 23 | $result->port = $port; 24 | $result->reloadWorld = $reloadWorld; 25 | return $result; 26 | } 27 | 28 | protected function decodePayload(PacketSerializer $in) : void{ 29 | $this->address = $in->getString(); 30 | $this->port = $in->getLShort(); 31 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 32 | $this->reloadWorld = $in->getBool(); 33 | } 34 | } 35 | 36 | protected function encodePayload(PacketSerializer $out) : void{ 37 | $out->putString($this->address); 38 | $out->putLShort($this->port); 39 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 40 | $out->putBool($this->reloadWorld); 41 | } 42 | } 43 | 44 | public function getConstructorArguments(PM_Packet $packet) : array { 45 | return [ 46 | $packet->address, 47 | $packet->port, 48 | $packet->reloadWorld ?? false, 49 | ]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/UpdateAbilitiesPacket.php: -------------------------------------------------------------------------------- 1 | data = $data; 26 | return $result; 27 | } 28 | 29 | public function getData() : PM_AbilitiesData{ return $this->data; } 30 | 31 | protected function decodePayload(PacketSerializer $in) : void { 32 | $this->data = AbilitiesData::decode($in); 33 | } 34 | 35 | protected function encodePayload(PacketSerializer $out) : void { 36 | $this->data->encode($out); 37 | } 38 | 39 | public function getConstructorArguments(PM_Packet $packet) : array { 40 | return [ 41 | $packet->data 42 | ]; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/UpdateAttributesPacket.php: -------------------------------------------------------------------------------- 1 | actorRuntimeId = $actorRuntimeId; 25 | $result->entries = $entries; 26 | $result->tick = $tick; 27 | return $result; 28 | } 29 | 30 | protected function decodePayload(PacketSerializer $in) : void{ 31 | $this->actorRuntimeId = $in->getActorRuntimeId(); 32 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 33 | $this->entries[] = CustomUpdateAttribute::read($in); 34 | } 35 | $this->tick = $in->getUnsignedVarLong(); 36 | } 37 | 38 | protected function encodePayload(PacketSerializer $out) : void{ 39 | $out->putActorRuntimeId($this->actorRuntimeId); 40 | $out->putUnsignedVarInt(count($this->entries)); 41 | foreach($this->entries as $entry){ 42 | $entry->write($out); 43 | } 44 | $out->putUnsignedVarLong($this->tick); 45 | } 46 | 47 | public function getConstructorArguments(PM_Packet $packet) : array { 48 | $entries = []; 49 | foreach ($packet->entries as $label => $entry) { 50 | $entries[$label] = new CustomUpdateAttribute( 51 | $entry->getId(), 52 | $entry->getMin(), 53 | $entry->getMax(), 54 | $entry->getCurrent(), 55 | $entry->getDefaultMin(), 56 | $entry->getDefaultMax(), 57 | $entry->getDefault(), 58 | $entry->getModifiers() 59 | ); 60 | } 61 | return [ 62 | $packet->actorRuntimeId, 63 | $entries, 64 | $packet->tick 65 | ]; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/UpdatePlayerGameTypePacket.php: -------------------------------------------------------------------------------- 1 | gameMode = $gameMode; 24 | $result->playerActorUniqueId = $playerActorUniqueId; 25 | $result->tick = $tick; 26 | return $result; 27 | } 28 | 29 | public function getGameMode() : int{ return $this->gameMode; } 30 | 31 | public function getPlayerActorUniqueId() : int{ return $this->playerActorUniqueId; } 32 | 33 | public function getTick() : int{ return $this->tick; } 34 | 35 | protected function decodePayload(PacketSerializer $in) : void{ 36 | $this->gameMode = $in->getVarInt(); 37 | $this->playerActorUniqueId = $in->getActorUniqueId(); 38 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40){ 39 | $this->tick = $in->getUnsignedVarLong(); 40 | }elseif($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_80){ 41 | $this->tick = $in->getUnsignedVarInt(); 42 | } 43 | } 44 | 45 | protected function encodePayload(PacketSerializer $out) : void{ 46 | $out->putVarInt($this->gameMode); 47 | $out->putActorUniqueId($this->playerActorUniqueId); 48 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40) { 49 | $out->putUnsignedVarLong($this->tick); 50 | }elseif($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_80) { 51 | $out->putUnsignedVarInt($this->tick); 52 | } 53 | } 54 | 55 | public function getConstructorArguments(PM_Packet $packet) : array 56 | { 57 | return [ 58 | $packet->getGameMode(), 59 | $packet->getPlayerActorUniqueId(), 60 | $packet->getTick() ?? 0 61 | ]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/serializer/CustomBitSet.php: -------------------------------------------------------------------------------- 1 | $expectedPartsCount){ 32 | throw new \InvalidArgumentException("Too many parts"); 33 | }elseif($partsCount < $expectedPartsCount){ 34 | $parts = array_pad($parts, $expectedPartsCount, 0); 35 | } 36 | 37 | $this->parts = array_values($parts); 38 | } 39 | 40 | public function get(int $index) : bool{ 41 | [$partIndex, $bitIndex] = $this->getPartIndex($index); 42 | 43 | return ($this->parts[$partIndex] & (1 << $bitIndex)) !== 0; 44 | } 45 | 46 | public function set(int $index, bool $value) : void{ 47 | [$partIndex, $bitIndex] = $this->getPartIndex($index); 48 | 49 | if($value){ 50 | $this->parts[$partIndex] |= 1 << $bitIndex; 51 | }else{ 52 | $this->parts[$partIndex] &= ~(1 << $bitIndex); 53 | } 54 | } 55 | 56 | /** 57 | * Returns the part index and the bit index within that part for a given bit index. 58 | * 59 | * @return array{int, int} 60 | */ 61 | private function getPartIndex(int $index) : array{ 62 | if($index < 0 || $index >= $this->length){ 63 | throw new \InvalidArgumentException("Index out of bounds"); 64 | } 65 | 66 | return [ 67 | intdiv($index, self::INT_BITS), 68 | $index % self::INT_BITS 69 | ]; 70 | } 71 | 72 | /** 73 | * @internal 74 | */ 75 | public function getPartsCount() : int{ 76 | return count($this->parts); 77 | } 78 | 79 | /** 80 | * @return int[] 81 | */ 82 | public function getParts() : array{ 83 | return $this->parts; 84 | } 85 | 86 | private static function getExpectedPartsCount(int $length) : int{ 87 | return intdiv($length + self::INT_BITS - 1, self::INT_BITS); 88 | } 89 | 90 | public static function read(PacketSerializer $in, int $length) : self{ 91 | $result = [0]; 92 | 93 | $currentIndex = 0; 94 | $currentShift = 0; 95 | 96 | for($i = 0; $i < $length; $i += self::SHIFT){ 97 | $b = $in->getByte(); 98 | $bits = $b & 0x7f; 99 | 100 | $result[$currentIndex] |= $bits << $currentShift; //extra bits will be discarded 101 | $nextShift = $currentShift + self::SHIFT; 102 | if($nextShift >= self::INT_BITS){ 103 | $nextShift -= self::INT_BITS; 104 | $rightShift = self::SHIFT - $nextShift; 105 | $result[++$currentIndex] = $bits >> $rightShift; 106 | } 107 | $currentShift = $nextShift; 108 | 109 | if(($b & 0x80) === 0){ 110 | return new self($length, array_slice($result, 0, self::getExpectedPartsCount($length))); 111 | } 112 | } 113 | 114 | return new self($length, array_slice($result, 0, self::getExpectedPartsCount($length))); 115 | } 116 | 117 | public function write(PacketSerializer $out, int $length = null) : void{ 118 | $parts = $this->parts; 119 | $length ??= $this->length; 120 | 121 | if($length > $this->length){ 122 | throw new \InvalidArgumentException("Cannot write more bits than the BitSet contains"); 123 | } 124 | 125 | $currentIndex = 0; 126 | $currentShift = 0; 127 | 128 | for($i = 0; $i < $length; $i += self::SHIFT){ 129 | $bits = $parts[$currentIndex] >> $currentShift; 130 | $nextShift = $currentShift + self::SHIFT; 131 | if($nextShift >= self::INT_BITS){ 132 | $nextShift -= self::INT_BITS; 133 | $bits |= ($parts[++$currentIndex] ?? 0) << (self::SHIFT - $nextShift); 134 | } 135 | $currentShift = $nextShift; 136 | 137 | $last = $i + self::SHIFT >= $length; 138 | $bits |= $last ? 0 : 0x80; 139 | 140 | $out->putByte($bits); 141 | if($last){ 142 | break; 143 | } 144 | } 145 | } 146 | 147 | public function getLength() : int{ 148 | return $this->length; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/AbilitiesData.php: -------------------------------------------------------------------------------- 1 | $abilityLayers 15 | */ 16 | public function __construct( 17 | private int $commandPermission, 18 | private int $playerPermission, 19 | private int $targetActorUniqueId, //This is a little-endian long, NOT a var-long. (WTF Mojang) 20 | private array $abilityLayers 21 | ){} 22 | 23 | public function getCommandPermission() : int{ return $this->commandPermission; } 24 | 25 | public function getPlayerPermission() : int{ return $this->playerPermission; } 26 | 27 | public function getTargetActorUniqueId() : int{ return $this->targetActorUniqueId; } 28 | 29 | /** 30 | * @return AbilitiesLayer[] 31 | * @phpstan-return array 32 | */ 33 | public function getAbilityLayers() : array{ return $this->abilityLayers; } 34 | 35 | public static function decode(PacketSerializer $in) : self { 36 | $targetActorUniqueId = $in->getLLong(); //WHY IS THIS NON-STANDARD? 37 | $playerPermission = $in->getByte(); 38 | $commandPermission = $in->getByte(); 39 | 40 | $abilityLayers = []; 41 | for($i = 0, $len = $in->getByte(); $i < $len; $i++){ 42 | $abilityLayers[] = AbilitiesLayer::decode($in); 43 | } 44 | 45 | return new self($commandPermission, $playerPermission, $targetActorUniqueId, $abilityLayers); 46 | } 47 | 48 | public function encode(PacketSerializer $out) : void { 49 | $out->putLLong($this->targetActorUniqueId); 50 | $out->putByte($this->playerPermission); 51 | $out->putByte($this->commandPermission); 52 | 53 | $out->putByte(count($this->abilityLayers)); 54 | foreach($this->abilityLayers as $abilityLayer){ 55 | $abilityLayer->encode($out); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/AbilitiesLayer.php: -------------------------------------------------------------------------------- 1 | $boolAbilities 46 | */ 47 | public function __construct( 48 | private int $layerId, 49 | private array $boolAbilities, 50 | private ?float $flySpeed, 51 | private ?float $verticalFlySpeed, 52 | private ?float $walkSpeed 53 | ){} 54 | 55 | public function getLayerId() : int{ return $this->layerId; } 56 | 57 | /** 58 | * Returns a list of abilities set/overridden by this layer. If the ability value is not set, the index is omitted. 59 | * @return bool[] 60 | * @phpstan-return array 61 | */ 62 | public function getBoolAbilities() : array{ return $this->boolAbilities; } 63 | 64 | public function getFlySpeed() : ?float{ return $this->flySpeed; } 65 | 66 | public function getVerticalFlySpeed() : ?float{ return $this->verticalFlySpeed; } 67 | 68 | public function getWalkSpeed() : ?float{ return $this->walkSpeed; } 69 | 70 | public static function decode(PacketSerializer $in) : self{ 71 | $layerId = $in->getLShort(); 72 | $setAbilities = $in->getLInt(); 73 | $setAbilityValues = $in->getLInt(); 74 | $flySpeed = $in->getLFloat(); 75 | $verticalFlySpeed = $in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60 ? $in->getLFloat() : 0.0; 76 | $walkSpeed = $in->getLFloat(); 77 | 78 | $boolAbilities = []; 79 | for($i = 0; $i < self::NUMBER_OF_ABILITIES; $i++){ 80 | if($i === self::ABILITY_FLY_SPEED || $i === self::ABILITY_WALK_SPEED){ 81 | continue; 82 | } 83 | if(($setAbilities & (1 << $i)) !== 0){ 84 | $boolAbilities[$i] = ($setAbilityValues & (1 << $i)) !== 0; 85 | } 86 | } 87 | if(($setAbilities & (1 << self::ABILITY_FLY_SPEED)) === 0){ 88 | if($flySpeed !== 0.0){ 89 | throw new PacketDecodeException("Fly speed should be zero if the layer does not set it"); 90 | } 91 | $flySpeed = null; 92 | } 93 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60 && ($setAbilities & (1 << self::ABILITY_VERTICAL_FLY_SPEED)) === 0){ 94 | if($verticalFlySpeed !== 0.0){ 95 | throw new PacketDecodeException("Vertical fly speed should be zero if the layer does not set it"); 96 | } 97 | $verticalFlySpeed = null; 98 | } 99 | if(($setAbilities & (1 << self::ABILITY_WALK_SPEED)) === 0){ 100 | if($walkSpeed !== 0.0){ 101 | throw new PacketDecodeException("Walk speed should be zero if the layer does not set it"); 102 | } 103 | $walkSpeed = null; 104 | } 105 | 106 | return new self($layerId, $boolAbilities, $flySpeed, $verticalFlySpeed, $walkSpeed); 107 | } 108 | 109 | public function encode(PacketSerializer $out) : void{ 110 | $out->putLShort($this->layerId); 111 | 112 | $setAbilities = 0; 113 | $setAbilityValues = 0; 114 | foreach($this->boolAbilities as $ability => $value){ 115 | $setAbilities |= (1 << $ability); 116 | $setAbilityValues |= ($value ? 1 << $ability : 0); 117 | } 118 | if($this->flySpeed !== null){ 119 | $setAbilities |= (1 << self::ABILITY_FLY_SPEED); 120 | } 121 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60 && $this->verticalFlySpeed !== null){ 122 | $setAbilities |= (1 << self::ABILITY_VERTICAL_FLY_SPEED); 123 | } 124 | if($this->walkSpeed !== null){ 125 | $setAbilities |= (1 << self::ABILITY_WALK_SPEED); 126 | } 127 | 128 | $out->putLInt($setAbilities); 129 | $out->putLInt($setAbilityValues); 130 | $out->putLFloat($this->flySpeed ?? 0); 131 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 132 | $out->putLFloat($this->verticalFlySpeed ?? 0); 133 | } 134 | $out->putLFloat($this->walkSpeed ?? 0); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/CustomItemInteractionData.php: -------------------------------------------------------------------------------- 1 | requestId; 25 | } 26 | 27 | /** 28 | * @return InventoryTransactionChangedSlotsHack[] 29 | */ 30 | public function getRequestChangedSlots() : array{ 31 | return $this->requestChangedSlots; 32 | } 33 | 34 | public function getTransactionData() : UseItemTransactionData{ 35 | return $this->transactionData; 36 | } 37 | 38 | public static function read(PacketSerializer $in) : self{ 39 | $requestId = $in->getVarInt(); 40 | $requestChangedSlots = []; 41 | if($requestId !== 0){ 42 | $len = $in->getUnsignedVarInt(); 43 | for($i = 0; $i < $len; ++$i){ 44 | $requestChangedSlots[] = InventoryTransactionChangedSlotsHack::read($in); 45 | } 46 | } 47 | $transactionData = new CustomUseItemTransactionData(); 48 | $transactionData->decode($in); 49 | return new self($requestId, $requestChangedSlots, $transactionData); 50 | } 51 | 52 | public function write(PacketSerializer $out) : void{ 53 | $out->putVarInt($this->requestId); 54 | if($this->requestId !== 0){ 55 | $out->putUnsignedVarInt(count($this->requestChangedSlots)); 56 | foreach($this->requestChangedSlots as $changedSlot){ 57 | $changedSlot->write($out); 58 | } 59 | } 60 | $this->transactionData->encode($out); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/CustomUpdateAttribute.php: -------------------------------------------------------------------------------- 1 | id; } 29 | 30 | public function getMin() : float{ return $this->min; } 31 | 32 | public function getMax() : float{ return $this->max; } 33 | 34 | public function getCurrent() : float{ return $this->current; } 35 | 36 | public function getDefaultMin() : float{ return $this->defaultMin; } 37 | 38 | public function getDefaultMax() : float{ return $this->defaultMax; } 39 | 40 | public function getDefault() : float{ return $this->default; } 41 | 42 | /** 43 | * @return AttributeModifier[] 44 | */ 45 | public function getModifiers() : array{ return $this->modifiers; } 46 | 47 | public static function read(PacketSerializer $in) : self{ 48 | $min = $in->getLFloat(); 49 | $max = $in->getLFloat(); 50 | $current = $in->getLFloat(); 51 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 52 | $defaultMin = $in->getLFloat(); 53 | $defaultMax = $in->getLFloat(); 54 | } 55 | $default = $in->getLFloat(); 56 | $id = $in->getString(); 57 | 58 | $modifiers = []; 59 | for($j = 0, $modifierCount = $in->getUnsignedVarInt(); $j < $modifierCount; $j++){ 60 | $modifiers[] = AttributeModifier::read($in); 61 | } 62 | 63 | return new self($id, $min, $max, $current, $defaultMin ?? $min, $defaultMax ?? $max, $default, $modifiers); 64 | } 65 | 66 | public function write(PacketSerializer $out) : void{ 67 | $out->putLFloat($this->min); 68 | $out->putLFloat($this->max); 69 | $out->putLFloat($this->current); 70 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 71 | $out->putLFloat($this->defaultMin); 72 | $out->putLFloat($this->defaultMax); 73 | } 74 | $out->putLFloat($this->default); 75 | $out->putString($this->id); 76 | 77 | $out->putUnsignedVarInt(count($this->modifiers)); 78 | foreach($this->modifiers as $modifier){ 79 | $modifier->write($out); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/CreativeItemEntry.php: -------------------------------------------------------------------------------- 1 | entryId; } 19 | 20 | public function getItem() : ItemStack{ return $this->item; } 21 | 22 | public function getGroupId() : int{ return $this->groupId; } 23 | 24 | public static function read(PacketSerializer $in) : self{ 25 | $entryId = $in->readCreativeItemNetId(); 26 | $item = $in->getItemStackWithoutStackId(); 27 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 28 | $groupId = $in->getUnsignedVarInt(); 29 | } 30 | return new self($entryId, $item, $groupId ?? -1); 31 | } 32 | 33 | public function write(PacketSerializer $out) : void{ 34 | $out->writeCreativeItemNetId($this->entryId); 35 | $out->putItemStackWithoutStackId($this->item); 36 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_60){ 37 | $out->putUnsignedVarInt($this->groupId); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/CustomUseItemTransactionData.php: -------------------------------------------------------------------------------- 1 | actionType; 42 | } 43 | 44 | public function getTriggerType() : TriggerType{ return $this->triggerType; } 45 | 46 | public function getBlockPosition() : BlockPosition{ 47 | return $this->blockPosition; 48 | } 49 | 50 | public function getFace() : int{ 51 | return $this->face; 52 | } 53 | 54 | public function getHotbarSlot() : int{ 55 | return $this->hotbarSlot; 56 | } 57 | 58 | public function getItemInHand() : ItemStackWrapper{ 59 | return $this->itemInHand; 60 | } 61 | 62 | public function getPlayerPosition() : Vector3{ 63 | return $this->playerPosition; 64 | } 65 | 66 | public function getClickPosition() : Vector3{ 67 | return $this->clickPosition; 68 | } 69 | 70 | public function getBlockRuntimeId() : int{ 71 | return $this->blockRuntimeId; 72 | } 73 | 74 | public function getClientInteractPrediction() : PredictedResult{ return $this->clientInteractPrediction; } 75 | 76 | protected function decodeData(PacketSerializer $stream) : void{ 77 | $this->actionType = $stream->getUnsignedVarInt(); 78 | if($stream->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 79 | $this->triggerType = TriggerType::fromPacket($stream->getUnsignedVarInt()); 80 | } 81 | $this->blockPosition = $stream->getBlockPosition(); 82 | $this->face = $stream->getVarInt(); 83 | $this->hotbarSlot = $stream->getVarInt(); 84 | $this->itemInHand = $stream->getItemStackWrapper(); 85 | $this->playerPosition = $stream->getVector3(); 86 | $this->clickPosition = $stream->getVector3(); 87 | $this->blockRuntimeId = $stream->getUnsignedVarInt(); 88 | if($stream->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 89 | $this->clientInteractPrediction = PredictedResult::fromPacket($stream->getUnsignedVarInt()); 90 | } 91 | } 92 | 93 | protected function encodeData(PacketSerializer $stream) : void{ 94 | $stream->putUnsignedVarInt($this->actionType); 95 | if($stream->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 96 | $stream->putUnsignedVarInt($this->triggerType->value); 97 | } 98 | $stream->putBlockPosition($this->blockPosition); 99 | $stream->putVarInt($this->face); 100 | $stream->putVarInt($this->hotbarSlot); 101 | $stream->putItemStackWrapper($this->itemInHand); 102 | $stream->putVector3($this->playerPosition); 103 | $stream->putVector3($this->clickPosition); 104 | $stream->putUnsignedVarInt($this->blockRuntimeId); 105 | if($stream->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 106 | $stream->putUnsignedVarInt($this->clientInteractPrediction->value); 107 | } 108 | } 109 | 110 | /** 111 | * @param NetworkInventoryAction[] $actions 112 | */ 113 | public static function new(array $actions, int $actionType, TriggerType $triggerType, BlockPosition $blockPosition, int $face, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $playerPosition, Vector3 $clickPosition, int $blockRuntimeId, PredictedResult $clientInteractPrediction) : self{ 114 | $result = new self(); 115 | $result->actions = $actions; 116 | $result->actionType = $actionType; 117 | $result->triggerType = $triggerType; 118 | $result->blockPosition = $blockPosition; 119 | $result->face = $face; 120 | $result->hotbarSlot = $hotbarSlot; 121 | $result->itemInHand = $itemInHand; 122 | $result->playerPosition = $playerPosition; 123 | $result->clickPosition = $clickPosition; 124 | $result->blockRuntimeId = $blockRuntimeId; 125 | $result->clientInteractPrediction = $clientInteractPrediction; 126 | return $result; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/FullContainerName.php: -------------------------------------------------------------------------------- 1 | containerId; } 17 | 18 | public function getDynamicId() : ?int{ return $this->dynamicId; } 19 | 20 | public static function read(PacketSerializer $in) : self{ 21 | $containerId = $in->getByte(); 22 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 23 | $dynamicId = $in->readOptional($in->getLInt(...)); 24 | }elseif($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 25 | $dynamicId = $in->getLInt(); 26 | } 27 | return new self($containerId, $dynamicId ?? null); 28 | } 29 | 30 | public function write(PacketSerializer $out) : void{ 31 | $out->putByte($this->containerId); 32 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_30){ 33 | $out->writeOptional($this->dynamicId, $out->putLInt(...)); 34 | }elseif($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 35 | $out->putLInt($this->dynamicId ?? 0); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/CraftRecipeAutoStackRequestAction.php: -------------------------------------------------------------------------------- 1 | $ingredients 27 | */ 28 | final public function __construct( 29 | private int $recipeId, 30 | private int $repetitions, 31 | private int $repetitions2, 32 | private array $ingredients 33 | ){} 34 | 35 | public function getRecipeId() : int{ return $this->recipeId; } 36 | 37 | public function getRepetitions() : int{ return $this->repetitions; } 38 | 39 | public function getRepetitions2() : int{ return $this->repetitions2; } 40 | 41 | /** 42 | * @return RecipeIngredient[] 43 | * @phpstan-return list 44 | */ 45 | public function getIngredients() : array{ return $this->ingredients; } 46 | 47 | public static function read(PacketSerializer $in) : self{ 48 | $recipeId = $in->readRecipeNetId(); 49 | $repetitions = $in->getByte(); 50 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 51 | $repetitions2 = $in->getByte(); //repetitions property is sent twice, mojang... 52 | } 53 | $ingredients = []; 54 | for($i = 0, $count = $in->getByte(); $i < $count; ++$i){ 55 | $ingredients[] = $in->getRecipeIngredient(); 56 | } 57 | return new self($recipeId, $repetitions, $repetitions2 ?? 0, $ingredients); 58 | } 59 | 60 | public function write(PacketSerializer $out) : void{ 61 | $out->writeRecipeNetId($this->recipeId); 62 | $out->putByte($this->repetitions); 63 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 64 | $out->putByte($this->repetitions2); 65 | } 66 | $out->putByte(count($this->ingredients)); 67 | foreach($this->ingredients as $ingredient){ 68 | $out->putRecipeIngredient($ingredient); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/CraftRecipeStackRequestAction.php: -------------------------------------------------------------------------------- 1 | recipeId; } 27 | 28 | public function getRepetitions() : int{ return $this->repetitions; } 29 | 30 | public static function read(PacketSerializer $in) : self{ 31 | $recipeId = $in->readRecipeNetId(); 32 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 33 | $repetitions = $in->getByte(); 34 | } 35 | return new self($recipeId, $repetitions ?? 0); 36 | } 37 | 38 | public function write(PacketSerializer $out) : void{ 39 | $out->writeRecipeNetId($this->recipeId); 40 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 41 | $out->putByte($this->repetitions); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/CraftingConsumeInputStackRequestAction.php: -------------------------------------------------------------------------------- 1 | creativeItemId; } 27 | 28 | public function getRepetitions() : int{ return $this->repetitions; } 29 | 30 | public static function read(PacketSerializer $in) : self{ 31 | $creativeItemId = $in->readCreativeItemNetId(); 32 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 33 | $repetitions = $in->getByte(); 34 | } 35 | return new self($creativeItemId, $repetitions ?? 0); 36 | } 37 | 38 | public function write(PacketSerializer $out) : void{ 39 | $out->writeCreativeItemNetId($this->creativeItemId); 40 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 41 | $out->putByte($this->repetitions); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/DestroyStackRequestAction.php: -------------------------------------------------------------------------------- 1 | count; } 16 | 17 | final public function getSource() : ItemStackRequestSlotInfo{ return $this->source; } 18 | 19 | public static function read(PacketSerializer $in) : self{ 20 | $count = $in->getByte(); 21 | $source = ItemStackRequestSlotInfo::read($in); 22 | return new self($count, $source); 23 | } 24 | 25 | public function write(PacketSerializer $out) : void{ 26 | $out->putByte($this->count); 27 | $this->source->write($out); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/DropStackRequestAction.php: -------------------------------------------------------------------------------- 1 | count; } 27 | 28 | public function getSource() : ItemStackRequestSlotInfo{ return $this->source; } 29 | 30 | public function isRandomly() : bool{ return $this->randomly; } 31 | 32 | public static function read(PacketSerializer $in) : self{ 33 | $count = $in->getByte(); 34 | $source = ItemStackRequestSlotInfo::read($in); 35 | $random = $in->getBool(); 36 | return new self($count, $source, $random); 37 | } 38 | 39 | public function write(PacketSerializer $out) : void{ 40 | $out->putByte($this->count); 41 | $this->source->write($out); 42 | $out->putBool($this->randomly); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/GrindstoneStackRequestAction.php: -------------------------------------------------------------------------------- 1 | recipeId; } 28 | 29 | /** WARNING: This may be negative */ 30 | public function getRepairCost() : int{ return $this->repairCost; } 31 | 32 | public function getRepetitions() : int{ return $this->repetitions; } 33 | 34 | public static function read(PacketSerializer $in) : self{ 35 | $recipeId = $in->readRecipeNetId(); 36 | $repairCost = $in->getVarInt(); //WHY!!!! 37 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 38 | $repetitions = $in->getByte(); 39 | } 40 | 41 | return new self($recipeId, $repairCost, $repetitions ?? 0); 42 | } 43 | 44 | public function write(PacketSerializer $out) : void{ 45 | $out->writeRecipeNetId($this->recipeId); 46 | $out->putVarInt($this->repairCost); 47 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 48 | $out->putByte($this->repetitions); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/ItemStackRequestSlotInfo.php: -------------------------------------------------------------------------------- 1 | containerName; } 18 | 19 | public function getSlotId() : int{ return $this->slotId; } 20 | 21 | public function getStackId() : int{ return $this->stackId; } 22 | 23 | public static function read(PacketSerializer $in) : self{ 24 | $containerName = FullContainerName::read($in); 25 | $slotId = $in->getByte(); 26 | $stackId = $in->readItemStackNetIdVariant(); 27 | return new self($containerName, $slotId, $stackId); 28 | } 29 | 30 | public function write(PacketSerializer $out) : void{ 31 | $this->containerName->write($out); 32 | $out->putByte($this->slotId); 33 | $out->writeItemStackNetIdVariant($this->stackId); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/PlaceIntoBundleStackRequestAction.php: -------------------------------------------------------------------------------- 1 | slot1; } 26 | 27 | public function getSlot2() : ItemStackRequestSlotInfo{ return $this->slot2; } 28 | 29 | public static function read(PacketSerializer $in) : self{ 30 | $slot1 = ItemStackRequestSlotInfo::read($in); 31 | $slot2 = ItemStackRequestSlotInfo::read($in); 32 | return new self($slot1, $slot2); 33 | } 34 | 35 | public function write(PacketSerializer $out) : void{ 36 | $this->slot1->write($out); 37 | $this->slot2->write($out); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/TakeFromBundleStackRequestAction.php: -------------------------------------------------------------------------------- 1 | count; } 17 | 18 | final public function getSource() : ItemStackRequestSlotInfo{ return $this->source; } 19 | 20 | final public function getDestination() : ItemStackRequestSlotInfo{ return $this->destination; } 21 | 22 | public static function read(PacketSerializer $in) : self{ 23 | $count = $in->getByte(); 24 | $src = ItemStackRequestSlotInfo::read($in); 25 | $dst = ItemStackRequestSlotInfo::read($in); 26 | return new self($count, $src, $dst); 27 | } 28 | 29 | public function write(PacketSerializer $out) : void{ 30 | $out->putByte($this->count); 31 | $this->source->write($out); 32 | $this->destination->write($out); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackrequest/TakeStackRequestAction.php: -------------------------------------------------------------------------------- 1 | result !== self::RESULT_OK && count($this->containerInfos) !== 0){ 26 | throw new \InvalidArgumentException("Container infos must be empty if rejecting the request"); 27 | } 28 | } 29 | 30 | public function getResult() : int{ return $this->result; } 31 | 32 | public function getRequestId() : int{ return $this->requestId; } 33 | 34 | /** @return ItemStackResponseContainerInfo[] */ 35 | public function getContainerInfos() : array{ return $this->containerInfos; } 36 | 37 | public static function read(PacketSerializer $in) : self{ 38 | $result = $in->getByte(); 39 | $requestId = $in->readItemStackRequestId(); 40 | $containerInfos = []; 41 | if($result === self::RESULT_OK){ 42 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 43 | $containerInfos[] = ItemStackResponseContainerInfo::read($in); 44 | } 45 | } 46 | return new self($result, $requestId, $containerInfos); 47 | } 48 | 49 | public function write(PacketSerializer $out) : void{ 50 | $out->putByte($this->result); 51 | $out->writeItemStackRequestId($this->requestId); 52 | if($this->result === self::RESULT_OK){ 53 | $out->putUnsignedVarInt(count($this->containerInfos)); 54 | foreach($this->containerInfos as $containerInfo){ 55 | $containerInfo->write($out); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackresponse/ItemStackResponseContainerInfo.php: -------------------------------------------------------------------------------- 1 | containerName; } 21 | 22 | /** @return ItemStackResponseSlotInfo[] */ 23 | public function getSlots() : array{ return $this->slots; } 24 | 25 | public static function read(PacketSerializer $in) : self{ 26 | $containerName = FullContainerName::read($in); 27 | $slots = []; 28 | for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ 29 | $slots[] = ItemStackResponseSlotInfo::read($in); 30 | } 31 | return new self($containerName, $slots); 32 | } 33 | 34 | public function write(PacketSerializer $out) : void{ 35 | $this->containerName->write($out); 36 | $out->putUnsignedVarInt(count($this->slots)); 37 | foreach($this->slots as $slot){ 38 | $slot->write($out); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/inventory/stackresponse/ItemStackResponseSlotInfo.php: -------------------------------------------------------------------------------- 1 | slot; } 22 | 23 | public function getHotbarSlot() : int{ return $this->hotbarSlot; } 24 | 25 | public function getCount() : int{ return $this->count; } 26 | 27 | public function getItemStackId() : int{ return $this->itemStackId; } 28 | 29 | public function getCustomName() : string{ return $this->customName; } 30 | 31 | public function getFilteredCustomName() : string{ return $this->filteredCustomName; } 32 | 33 | public function getDurabilityCorrection() : int{ return $this->durabilityCorrection; } 34 | 35 | public static function read(PacketSerializer $in) : self{ 36 | $slot = $in->getByte(); 37 | $hotbarSlot = $in->getByte(); 38 | $count = $in->getByte(); 39 | $itemStackId = $in->readServerItemStackId(); 40 | $customName = $in->getString(); 41 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_50){ 42 | $filteredCustomName = $in->getString(); 43 | } 44 | $durabilityCorrection = $in->getVarInt(); 45 | return new self($slot, $hotbarSlot, $count, $itemStackId, $customName, $filteredCustomName ?? $customName, $durabilityCorrection); 46 | } 47 | 48 | public function write(PacketSerializer $out) : void{ 49 | $out->putByte($this->slot); 50 | $out->putByte($this->hotbarSlot); 51 | $out->putByte($this->count); 52 | $out->writeServerItemStackId($this->itemStackId); 53 | $out->putString($this->customName); 54 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_50){ 55 | $out->putString($this->filteredCustomName); 56 | } 57 | $out->putVarInt($this->durabilityCorrection); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/recipe/CustomShapedRecipe.php: -------------------------------------------------------------------------------- 1 | 3){ 38 | throw new \InvalidArgumentException("Expected 1, 2 or 3 input rows"); 39 | } 40 | $columns = null; 41 | foreach($input as $rowNumber => $row){ 42 | if($columns === null){ 43 | $columns = count($row); 44 | }elseif(count($row) !== $columns){ 45 | throw new \InvalidArgumentException("Expected each row to be $columns columns, but have " . count($row) . " in row $rowNumber"); 46 | } 47 | } 48 | $this->blockName = $blockType; 49 | } 50 | 51 | public function getRecipeId() : string{ 52 | return $this->recipeId; 53 | } 54 | 55 | public function getWidth() : int{ 56 | return count($this->input[0]); 57 | } 58 | 59 | public function getHeight() : int{ 60 | return count($this->input); 61 | } 62 | 63 | /** 64 | * @return RecipeIngredient[][] 65 | */ 66 | public function getInput() : array{ 67 | return $this->input; 68 | } 69 | 70 | /** 71 | * @return ItemStack[] 72 | */ 73 | public function getOutput() : array{ 74 | return $this->output; 75 | } 76 | 77 | public function getUuid() : UuidInterface{ 78 | return $this->uuid; 79 | } 80 | 81 | public function getBlockName() : string{ 82 | return $this->blockName; 83 | } 84 | 85 | public function getPriority() : int{ 86 | return $this->priority; 87 | } 88 | 89 | public function isSymmetric() : bool{ return $this->symmetric; } 90 | 91 | public function getUnlockingRequirement() : RecipeUnlockingRequirement{ return $this->unlockingRequirement; } 92 | 93 | public function getRecipeNetId() : int{ 94 | return $this->recipeNetId; 95 | } 96 | 97 | public static function decode(int $recipeType, PacketSerializer $in) : self{ 98 | $recipeId = $in->getString(); 99 | $width = $in->getVarInt(); 100 | $height = $in->getVarInt(); 101 | $input = []; 102 | for($row = 0; $row < $height; ++$row){ 103 | for($column = 0; $column < $width; ++$column){ 104 | $input[$row][$column] = $in->getRecipeIngredient(); 105 | } 106 | } 107 | 108 | $output = []; 109 | for($k = 0, $resultCount = $in->getUnsignedVarInt(); $k < $resultCount; ++$k){ 110 | $output[] = $in->getItemStackWithoutStackId(); 111 | } 112 | $uuid = $in->getUUID(); 113 | $block = $in->getString(); 114 | $priority = $in->getVarInt(); 115 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_80){ 116 | $symmetric = $in->getBool(); 117 | 118 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 119 | $unlockingRequirement = RecipeUnlockingRequirement::read($in); 120 | } 121 | } 122 | 123 | $recipeNetId = $in->readRecipeNetId(); 124 | 125 | return new self($recipeType, $recipeId, $input, $output, $uuid, $block, $priority, $symmetric ?? true, $unlockingRequirement ?? new RecipeUnlockingRequirement(null), $recipeNetId); 126 | } 127 | 128 | public function encode(PacketSerializer $out) : void{ 129 | $out->putString($this->recipeId); 130 | $out->putVarInt($this->getWidth()); 131 | $out->putVarInt($this->getHeight()); 132 | foreach($this->input as $row){ 133 | foreach($row as $ingredient){ 134 | $out->putRecipeIngredient($ingredient); 135 | } 136 | } 137 | 138 | $out->putUnsignedVarInt(count($this->output)); 139 | foreach($this->output as $item){ 140 | $out->putItemStackWithoutStackId($item); 141 | } 142 | 143 | $out->putUUID($this->uuid); 144 | $out->putString($this->blockName); 145 | $out->putVarInt($this->priority); 146 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_20_80) { 147 | $out->putBool($this->symmetric); 148 | 149 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0) { 150 | $this->unlockingRequirement->write($out); 151 | } 152 | } 153 | $out->writeRecipeNetId($this->recipeNetId); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/recipe/CustomShapelessRecipe.php: -------------------------------------------------------------------------------- 1 | recipeId; 37 | } 38 | 39 | /** 40 | * @return RecipeIngredient[] 41 | */ 42 | public function getInputs() : array{ 43 | return $this->inputs; 44 | } 45 | 46 | /** 47 | * @return ItemStack[] 48 | */ 49 | public function getOutputs() : array{ 50 | return $this->outputs; 51 | } 52 | 53 | public function getUuid() : UuidInterface{ 54 | return $this->uuid; 55 | } 56 | 57 | public function getBlockName() : string{ 58 | return $this->blockName; 59 | } 60 | 61 | public function getPriority() : int{ 62 | return $this->priority; 63 | } 64 | 65 | public function getUnlockingRequirement() : RecipeUnlockingRequirement{ return $this->unlockingRequirement; } 66 | 67 | public function getRecipeNetId() : int{ 68 | return $this->recipeNetId; 69 | } 70 | 71 | public static function decode(int $recipeType, PacketSerializer $in) : self{ 72 | $recipeId = $in->getString(); 73 | $input = []; 74 | for($j = 0, $ingredientCount = $in->getUnsignedVarInt(); $j < $ingredientCount; ++$j){ 75 | $input[] = $in->getRecipeIngredient(); 76 | } 77 | $output = []; 78 | for($k = 0, $resultCount = $in->getUnsignedVarInt(); $k < $resultCount; ++$k){ 79 | $output[] = $in->getItemStackWithoutStackId(); 80 | } 81 | $uuid = $in->getUUID(); 82 | $block = $in->getString(); 83 | $priority = $in->getVarInt(); 84 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 85 | $unlockingRequirement = RecipeUnlockingRequirement::read($in); 86 | } 87 | 88 | $recipeNetId = $in->readRecipeNetId(); 89 | 90 | return new self($recipeType, $recipeId, $input, $output, $uuid, $block, $priority, $unlockingRequirement ?? new RecipeUnlockingRequirement(null), $recipeNetId); 91 | } 92 | 93 | public function encode(PacketSerializer $out) : void{ 94 | $out->putString($this->recipeId); 95 | $out->putUnsignedVarInt(count($this->inputs)); 96 | foreach($this->inputs as $item){ 97 | $out->putRecipeIngredient($item); 98 | } 99 | 100 | $out->putUnsignedVarInt(count($this->outputs)); 101 | foreach($this->outputs as $item){ 102 | $out->putItemStackWithoutStackId($item); 103 | } 104 | 105 | $out->putUUID($this->uuid); 106 | $out->putString($this->blockName); 107 | $out->putVarInt($this->priority); 108 | 109 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_0){ 110 | $this->unlockingRequirement->write($out); 111 | } 112 | 113 | $out->writeRecipeNetId($this->recipeNetId); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/resourcepacks/CustomBehaviourPackInfoEntry.php: -------------------------------------------------------------------------------- 1 | packId; 24 | } 25 | 26 | public function getVersion() : string{ 27 | return $this->version; 28 | } 29 | 30 | public function getSizeBytes() : int{ 31 | return $this->sizeBytes; 32 | } 33 | 34 | public function getEncryptionKey() : string{ 35 | return $this->encryptionKey; 36 | } 37 | 38 | public function getSubPackName() : string{ 39 | return $this->subPackName; 40 | } 41 | 42 | public function getContentId() : string{ 43 | return $this->contentId; 44 | } 45 | 46 | public function hasScripts() : bool{ 47 | return $this->hasScripts; 48 | } 49 | 50 | public function isAddonPack() : bool{ return $this->isAddonPack; } 51 | 52 | public function write(PacketSerializer $out) : void{ 53 | $out->putString($this->packId); 54 | $out->putString($this->version); 55 | $out->putLLong($this->sizeBytes); 56 | $out->putString($this->encryptionKey); 57 | $out->putString($this->subPackName); 58 | $out->putString($this->contentId); 59 | $out->putBool($this->hasScripts); 60 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 61 | $out->putBool($this->isAddonPack); 62 | } 63 | } 64 | 65 | public static function read(PacketSerializer $in) : self{ 66 | $uuid = $in->getString(); 67 | $version = $in->getString(); 68 | $sizeBytes = $in->getLLong(); 69 | $encryptionKey = $in->getString(); 70 | $subPackName = $in->getString(); 71 | $contentId = $in->getString(); 72 | $hasScripts = $in->getBool(); 73 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 74 | $isAddonPack = $in->getBool(); 75 | } 76 | return new self($uuid, $version, $sizeBytes, $encryptionKey, $subPackName, $contentId, $hasScripts, $isAddonPack ?? false); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/packets/types/resourcepacks/CustomResourcePackInfoEntry.php: -------------------------------------------------------------------------------- 1 | packId; 28 | } 29 | 30 | public function getVersion() : string{ 31 | return $this->version; 32 | } 33 | 34 | public function getSizeBytes() : int{ 35 | return $this->sizeBytes; 36 | } 37 | 38 | public function getEncryptionKey() : string{ 39 | return $this->encryptionKey; 40 | } 41 | 42 | public function getSubPackName() : string{ 43 | return $this->subPackName; 44 | } 45 | 46 | public function getContentId() : string{ 47 | return $this->contentId; 48 | } 49 | 50 | public function hasScripts() : bool{ 51 | return $this->hasScripts; 52 | } 53 | 54 | public function isAddonPack() : bool{ return $this->isAddonPack; } 55 | 56 | public function isRtxCapable() : bool{ return $this->isRtxCapable; } 57 | 58 | public function getCdnUrl() : string{ return $this->cdnUrl; } 59 | 60 | public function write(PacketSerializer $out) : void{ 61 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_50){ 62 | $out->putUUID($this->packId); 63 | }else{ 64 | $out->putString($this->packId->toString()); 65 | } 66 | $out->putString($this->version); 67 | $out->putLLong($this->sizeBytes); 68 | $out->putString($this->encryptionKey); 69 | $out->putString($this->subPackName); 70 | $out->putString($this->contentId); 71 | $out->putBool($this->hasScripts); 72 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 73 | $out->putBool($this->isAddonPack); 74 | } 75 | $out->putBool($this->isRtxCapable); 76 | if($out->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40) { 77 | $out->putString($this->cdnUrl); 78 | } 79 | } 80 | 81 | public static function read(PacketSerializer $in) : self{ 82 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_50){ 83 | $uuid = $in->getUUID(); 84 | }else{ 85 | $uuid = Uuid::fromString($in->getString()); 86 | } 87 | $version = $in->getString(); 88 | $sizeBytes = $in->getLLong(); 89 | $encryptionKey = $in->getString(); 90 | $subPackName = $in->getString(); 91 | $contentId = $in->getString(); 92 | $hasScripts = $in->getBool(); 93 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 94 | $isAddonPack = $in->getBool(); 95 | } 96 | $rtxCapable = $in->getBool(); 97 | if($in->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_40) { 98 | $cdnUrl = $in->getString(); 99 | } 100 | return new self($uuid, $version, $sizeBytes, $encryptionKey, $subPackName, $contentId, $hasScripts, $isAddonPack ?? false, $rtxCapable, $cdnUrl ?? ""); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/CustomPacketBatch.php: -------------------------------------------------------------------------------- 1 | 22 | * @throws PacketDecodeException 23 | */ 24 | final public static function decodeRaw(BinaryStream $stream) : \Generator{ 25 | $c = 0; 26 | while(!$stream->feof()){ 27 | try{ 28 | $length = $stream->getUnsignedVarInt(); 29 | $buffer = $stream->get($length); 30 | }catch(BinaryDataException $e){ 31 | throw new PacketDecodeException("Error decoding packet $c in batch: " . $e->getMessage(), 0, $e); 32 | } 33 | yield $buffer; 34 | $c++; 35 | } 36 | } 37 | 38 | /** 39 | * @param string[] $packets 40 | * @phpstan-param list $packets 41 | */ 42 | final public static function encodeRaw(BinaryStream $stream, array $packets) : void{ 43 | foreach($packets as $packet){ 44 | $stream->putUnsignedVarInt(strlen($packet)); 45 | $stream->put($packet); 46 | } 47 | } 48 | 49 | /** 50 | * @phpstan-return \Generator 51 | * @throws PacketDecodeException 52 | */ 53 | final public static function decodePackets(int $protocol, BinaryStream $stream, PacketPool $packetPool) : \Generator{ 54 | $c = 0; 55 | foreach(self::decodeRaw($stream) as $packetBuffer){ 56 | $packet = $packetPool->getPacket($packetBuffer); 57 | if($packet !== null){ 58 | try{ 59 | $decoder = CustomPacketSerializer::decoder($packetBuffer, 0); 60 | $decoder->setProtocol($protocol); 61 | 62 | $packet->decode($decoder); 63 | }catch(PacketDecodeException $e){ 64 | throw new PacketDecodeException("Error decoding packet $c in batch: " . $e->getMessage(), 0, $e); 65 | } 66 | yield $packet; 67 | }else{ 68 | throw new PacketDecodeException("Unknown packet $c in batch"); 69 | } 70 | $c++; 71 | } 72 | } 73 | 74 | /** 75 | * @param Packet[] $packets 76 | * @phpstan-param list $packets 77 | */ 78 | final public static function encodePackets(int $protocol, BinaryStream $stream, array $packets) : void{ 79 | foreach($packets as $packet){ 80 | $serializer = CustomPacketSerializer::encoder(); 81 | $serializer->setProtocol($protocol); 82 | $packet->encode($serializer); 83 | $stream->putUnsignedVarInt(strlen($serializer->getBuffer())); 84 | $stream->put($serializer->getBuffer()); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/CustomPacketSerializer.php: -------------------------------------------------------------------------------- 1 | getActorUniqueId(); 42 | $toActorUniqueId = $this->getActorUniqueId(); 43 | $type = $this->getByte(); 44 | $immediate = $this->getBool(); 45 | $causedByRider = $this->getBool(); 46 | if($this->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20){ 47 | $vehicleAngularVelocity = $this->getLFloat(); 48 | } 49 | return new EntityLink($fromActorUniqueId, $toActorUniqueId, $type, $immediate, $causedByRider, $vehicleAngularVelocity ?? 0.0); 50 | } 51 | 52 | public function putEntityLink(EntityLink $link) : void{ 53 | $this->putActorUniqueId($link->fromActorUniqueId); 54 | $this->putActorUniqueId($link->toActorUniqueId); 55 | $this->putByte($link->type); 56 | $this->putBool($link->immediate); 57 | $this->putBool($link->causedByRider); 58 | if($this->getProtocol() >= CustomProtocolInfo::PROTOCOL_1_21_20) { 59 | $this->putLFloat($link->vehicleAngularVelocity); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/CustomRuntimeIDtoStateID.php: -------------------------------------------------------------------------------- 1 | setProtocolInstance($this, $protocol); 20 | $blockTranslator = CustomTypeConverter::getInstance()->getBlockTranslator(); 21 | foreach (RuntimeBlockStateRegistry::getInstance()->getAllKnownStates() as $state) { 22 | $blockRuntimeId = $blockTranslator->internalIdToNetworkId($stateId = $state->getStateId()); 23 | $this->runtimeIdToStateId[$protocol][$blockRuntimeId] = $stateId; 24 | } 25 | } 26 | 27 | public function getStateIdFromRuntimeId(int $blockRuntimeId) : int 28 | { 29 | return $this->runtimeIdToStateId[$this->protocol][$blockRuntimeId] ?? 0; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/convert/CustomBlockStateDictionaryEntry.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | private static array $uniqueRawStates = []; 24 | 25 | private string $rawStateProperties; 26 | 27 | /** 28 | * @param Tag[] $stateProperties 29 | */ 30 | public function __construct( 31 | private string $stateName, 32 | array $stateProperties, 33 | private int $meta, 34 | private ?BlockStateData $oldBlockStateData 35 | ){ 36 | $rawStateProperties = self::encodeStateProperties($stateProperties); 37 | $this->rawStateProperties = self::$uniqueRawStates[$rawStateProperties] ??= $rawStateProperties; 38 | } 39 | 40 | public function getStateName() : string{ return $this->stateName; } 41 | 42 | public function getRawStateProperties() : string{ return $this->rawStateProperties; } 43 | 44 | public function generateStateData() : BlockStateData{ 45 | return $this->oldBlockStateData ?? $this->generateCurrentStateData(); 46 | } 47 | 48 | public function generateCurrentStateData() : BlockStateData{ 49 | return new BlockStateData( 50 | $this->stateName, 51 | self::decodeStateProperties($this->rawStateProperties), 52 | BlockStateData::CURRENT_VERSION 53 | ); 54 | } 55 | 56 | public function getMeta() : int{ return $this->meta; } 57 | 58 | /** 59 | * @return Tag[] 60 | */ 61 | public static function decodeStateProperties(string $rawProperties) : array{ 62 | if($rawProperties === ""){ 63 | return []; 64 | } 65 | return (new LittleEndianNbtSerializer())->read($rawProperties)->mustGetCompoundTag()->getValue(); 66 | } 67 | 68 | /** 69 | * @param Tag[] $properties 70 | */ 71 | public static function encodeStateProperties(array $properties) : string{ 72 | if(count($properties) === 0){ 73 | return ""; 74 | } 75 | ksort($properties, SORT_STRING); 76 | $tag = new CompoundTag(); 77 | foreach($properties as $k => $v){ 78 | $tag->setTag($k, $v); 79 | } 80 | return (new LittleEndianNbtSerializer())->write(new TreeRoot($tag)); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/convert/CustomItemIdMetaDowngrader.php: -------------------------------------------------------------------------------- 1 | $renamedIds 19 | */ 20 | private array $renamedIds = []; 21 | /** 22 | * @var string[][] $remappedMetas 23 | * @phpstan-var array $remappedMetas 24 | */ 25 | private array $remappedMetas = []; 26 | 27 | public function __construct(ItemTypeDictionary $dictionary, int $schemaId){ 28 | $upgrader = GlobalItemDataHandlers::getUpgrader()->getIdMetaUpgrader(); 29 | 30 | $networkIds = []; 31 | foreach($upgrader->getSchemas() as $id => $schema){ 32 | if($id <= $schemaId){ 33 | continue; 34 | } 35 | 36 | foreach(Utils::stringifyKeys($schema->getRenamedIds()) as $oldId => $newStringId){ 37 | if(isset($networkIds[$oldId])){ 38 | $networkIds[$newStringId] = $networkIds[$oldId]; 39 | }else{ 40 | try{ 41 | $dictionary->fromStringId($oldId); 42 | $networkIds[$newStringId] = $oldId; 43 | }catch(\InvalidArgumentException $e){ 44 | //ignore 45 | } 46 | } 47 | } 48 | 49 | foreach(Utils::stringifyKeys($schema->getRemappedMetas()) as $oldId => $metaToNewId){ 50 | if(isset($networkIds[$oldId])){ 51 | foreach($metaToNewId as $oldMeta => $newStringId){ 52 | if(is_array($networkIds[$oldId])){ 53 | throw new AssumptionFailedError("Can't flatten IDs twice"); 54 | }else{ 55 | $networkIds[$newStringId] = [$networkIds[$oldId], $oldMeta]; 56 | } 57 | } 58 | }else{ 59 | try{ 60 | $dictionary->fromStringId($oldId); 61 | foreach($metaToNewId as $oldMeta => $newStringId){ 62 | $networkIds[$newStringId] = [$oldId, $oldMeta]; 63 | } 64 | }catch(\InvalidArgumentException $e){ 65 | //ignore 66 | } 67 | } 68 | } 69 | } 70 | 71 | foreach(Utils::stringifyKeys($networkIds) as $newStringId => $oldId){ 72 | if(is_array($oldId)){ 73 | $this->remappedMetas[$newStringId] = $oldId; 74 | }else{ 75 | $this->renamedIds[$newStringId] = $oldId; 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * @phpstan-return array{string, int} 82 | */ 83 | public function downgrade(string $id, int $meta) : array{ 84 | $newId = $id; 85 | $newMeta = $meta; 86 | 87 | if(isset($this->remappedMetas[$newId])){ 88 | [$newId, $newMeta] = $this->remappedMetas[$newId]; 89 | }elseif(isset($this->renamedIds[$newId])){ 90 | $newId = $this->renamedIds[$newId]; 91 | } 92 | 93 | return [$newId, $newMeta]; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/convert/CustomItemTypeDictionaryFromDataHelper.php: -------------------------------------------------------------------------------- 1 | "", 31 | CustomProtocolInfo::PROTOCOL_1_21_60 => "-1.21.60", 32 | CustomProtocolInfo::PROTOCOL_1_21_50 => "-1.21.50", 33 | CustomProtocolInfo::PROTOCOL_1_21_40 => "-1.21.40", 34 | CustomProtocolInfo::PROTOCOL_1_21_30 => "-1.21.30", 35 | CustomProtocolInfo::PROTOCOL_1_21_20 => "-1.21.20", 36 | CustomProtocolInfo::PROTOCOL_1_21_2 => "-1.21.2", 37 | CustomProtocolInfo::PROTOCOL_1_21_0 => "-1.21.2", 38 | CustomProtocolInfo::PROTOCOL_1_20_80 => "-1.20.80", 39 | CustomProtocolInfo::PROTOCOL_1_20_70 => "-1.20.70", 40 | CustomProtocolInfo::PROTOCOL_1_20_60 => "-1.20.60", 41 | CustomProtocolInfo::PROTOCOL_1_20_50 => "-1.20.50", 42 | ]; 43 | 44 | public static function loadFromProtocolId(int $protocolId) : ItemTypeDictionary{ 45 | if(in_array($protocolId, CustomProtocolInfo::COMBINED_LATEST, true)){ 46 | $path = BedrockDataFiles::REQUIRED_ITEM_LIST_JSON; 47 | } else { 48 | $path = str_replace(".json", self::PATHS[$protocolId] . ".json", Main::getProtocolDataFolder() . '/required_item_list.json'); 49 | } 50 | return self::loadFromString(Filesystem::fileGetContents($path)); 51 | } 52 | 53 | public static function loadFromString(string $data) : ItemTypeDictionary{ 54 | $table = json_decode($data, true); 55 | if(!is_array($table)){ 56 | throw new AssumptionFailedError("Invalid item list format"); 57 | } 58 | 59 | $emptyNBT = new CacheableNbt(new CompoundTag()); 60 | $nbtSerializer = new LittleEndianNbtSerializer(); 61 | 62 | $params = []; 63 | foreach($table as $name => $entry){ 64 | if(!is_array($entry) || !is_string($name) || !isset($entry["component_based"], $entry["runtime_id"]) || !is_bool($entry["component_based"]) || !is_int($entry["runtime_id"]) || !is_int($entry["version"] ?? 0) || !(is_string($componentNbt = $entry["component_nbt"] ?? null) || $componentNbt === null)){ 65 | throw new AssumptionFailedError("Invalid item list format"); 66 | } 67 | $params[] = new ItemTypeEntry($name, $entry["runtime_id"], $entry["component_based"], $entry["version"] ?? 2, $componentNbt === null ? $emptyNBT : new CacheableNbt($nbtSerializer->read(ErrorToExceptionHandler::trapAndRemoveFalse(fn() => base64_decode($componentNbt, true)))->mustGetCompoundTag())); 68 | } 69 | return new ItemTypeDictionary($params); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/network/static/data/CustomGlobalItemDataHandlers.php: -------------------------------------------------------------------------------- 1 | "", 31 | CustomProtocolInfo::PROTOCOL_1_21_60 => "", 32 | CustomProtocolInfo::PROTOCOL_1_21_50 => "", 33 | CustomProtocolInfo::PROTOCOL_1_21_40 => "", 34 | CustomProtocolInfo::PROTOCOL_1_21_30 => "", 35 | CustomProtocolInfo::PROTOCOL_1_21_20 => "", 36 | CustomProtocolInfo::PROTOCOL_1_21_2 => "", 37 | CustomProtocolInfo::PROTOCOL_1_21_0 => "", 38 | CustomProtocolInfo::PROTOCOL_1_20_80 => "", 39 | CustomProtocolInfo::PROTOCOL_1_20_70 => "", 40 | CustomProtocolInfo::PROTOCOL_1_20_60 => "", 41 | CustomProtocolInfo::PROTOCOL_1_20_50 => "", 42 | //Support older versions if needed 43 | ]; 44 | 45 | private static function make(int $protocolId) : self{ 46 | $map = json_decode(Filesystem::fileGetContents(str_replace(".json", self::PATHS[$protocolId] . ".json", BedrockDataFiles::ITEM_TAGS_JSON)), true, flags: JSON_THROW_ON_ERROR); 47 | if(!is_array($map)){ 48 | throw new AssumptionFailedError("Invalid item tag map, expected array"); 49 | } 50 | $cleanMap = []; 51 | foreach(Utils::promoteKeys($map) as $tagName => $ids){ 52 | if(!is_string($tagName)){ 53 | throw new AssumptionFailedError("Invalid item tag name $tagName, expected string as key"); 54 | } 55 | if(!is_array($ids)){ 56 | throw new AssumptionFailedError("Invalid item tag $tagName, expected array of IDs as value"); 57 | } 58 | $cleanIds = []; 59 | foreach($ids as $id){ 60 | if(!is_string($id)){ 61 | throw new AssumptionFailedError("Invalid item tag $tagName, expected string as ID, got " . gettype($id)); 62 | } 63 | $cleanIds[] = $id; 64 | } 65 | $cleanMap[$tagName] = $cleanIds; 66 | } 67 | 68 | return new self($cleanMap); 69 | } 70 | 71 | /** 72 | * @var true[][] 73 | * @phpstan-var array> 74 | */ 75 | private array $tagToIdsMap = []; 76 | 77 | /** 78 | * @param string[][] $tagToIds 79 | * @phpstan-param array> $tagToIds 80 | */ 81 | public function __construct( 82 | array $tagToIds 83 | ){ 84 | foreach(Utils::stringifyKeys($tagToIds) as $tag => $ids){ 85 | foreach($ids as $id){ 86 | $this->tagToIdsMap[$tag][$id] = true; 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * @return string[] 93 | * @phpstan-return list 94 | */ 95 | public function getIdsForTag(string $tag) : array{ 96 | return array_keys($this->tagToIdsMap[$tag] ?? []); 97 | } 98 | 99 | public function tagContainsId(string $tag, string $id) : bool{ 100 | return isset($this->tagToIdsMap[$tag][$id]); 101 | } 102 | 103 | public function addIdToTag(string $tag, string $id) : void{ 104 | $this->tagToIdsMap[$tag][$id] = true; 105 | } 106 | 107 | /** 108 | * $this - $other 109 | * 110 | * @return array> 111 | */ 112 | public function diff(ItemTagToIdMap $other) : array{ 113 | $diff = []; 114 | foreach(Utils::stringifyKeys($this->tagToIdsMap) as $tag => $ids){ 115 | foreach(Utils::stringifyKeys($ids) as $id => $_){ 116 | if(!$other->tagContainsId($tag, $id)){ 117 | $diff[$tag][] = $id; 118 | } 119 | } 120 | } 121 | return $diff; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/utils/ProtocolSingletonTrait.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | public static function getAll(bool $create = false) : array{ 30 | if($create){ 31 | foreach(CustomProtocolInfo::ACCEPTED_PROTOCOLS as $protocolId){ 32 | self::getProtocolInstance($protocolId); 33 | } 34 | } 35 | 36 | return self::$instance; 37 | } 38 | 39 | public static function setProtocolInstance(self $instance, int $protocolId) : void{ 40 | self::$instance[$protocolId] = $instance; 41 | } 42 | 43 | public static function reset() : void{ 44 | self::$instance = []; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/utils/ProtocolUtils.php: -------------------------------------------------------------------------------- 1 | startTiming(); 42 | 43 | $threshold = $compressor->getCompressionThreshold(); 44 | if($threshold === null || strlen($buffer) < $compressor->getCompressionThreshold() && $protocol >= CustomProtocolInfo::PROTOCOL_1_20_60){ 45 | $compressionType = CompressionAlgorithm::NONE; 46 | $compressed = $buffer; 47 | 48 | }else{ 49 | $sync ??= !(ReflectionUtils::getProperty(Server::class, $server, "networkCompressionAsync")); 50 | 51 | if(!$sync && strlen($buffer) >= ReflectionUtils::getProperty(Server::class, $server, "networkCompressionAsyncThreshold")){ 52 | $promise = new CompressBatchPromise(); 53 | $task = new CompressBatchTask($buffer, $promise, $compressor, $protocol); 54 | $server->getAsyncPool()->submitTask($task); 55 | return $promise; 56 | } 57 | 58 | $compressionType = $compressor->getNetworkId(); 59 | $compressed = $compressor->compress($buffer); 60 | } 61 | 62 | return ($protocol >= CustomProtocolInfo::PROTOCOL_1_20_60 ? chr($compressionType) : '') . $compressed; 63 | }finally{ 64 | $timings->stopTiming(); 65 | } 66 | } 67 | 68 | // https://github.com/didntpot/MultiVersion/blob/master/src/MultiVersion/network/proto/v419/v419PacketTranslator.php#L244 69 | public static function injectClientData(int $p, array &$data) : void 70 | { 71 | // todo; make this prettier :yum: 72 | if($p <= CustomProtocolInfo::PROTOCOL_1_21_70) { 73 | $data["GraphicsMode"] = 0; 74 | if($p <= CustomProtocolInfo::PROTOCOL_1_21_30) { 75 | $data["MaxViewDistance"] = 0; 76 | $data["MemoryTier"] = 0; 77 | $data["PlatformType"] = 0; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/utils/ReflectionUtils.php: -------------------------------------------------------------------------------- 1 | getProperty($propertyName); 21 | }else{ 22 | $refProp = self::$propCache[$k]; 23 | } 24 | $refProp->setValue($instance, $value); 25 | } 26 | 27 | /** 28 | * @throws ReflectionException 29 | */ 30 | public static function getProperty(string $className, object $instance, string $propertyName) : mixed{ 31 | if(!isset(self::$propCache[$k = "$className - $propertyName"])){ 32 | $refClass = new ReflectionClass($className); 33 | $refProp = $refClass->getProperty($propertyName); 34 | }else{ 35 | $refProp = self::$propCache[$k]; 36 | } 37 | return $refProp->getValue($instance); 38 | } 39 | 40 | /** 41 | * @throws ReflectionException 42 | */ 43 | public static function getProperties(string $className, object $instance, array $propertiesNames) : array{ 44 | $result = []; 45 | foreach($propertiesNames as $propertyName) $result[$propertyName] = self::getProperty($className, $instance, $propertyName); 46 | return $result; 47 | } 48 | 49 | /** 50 | * @param mixed ...$args 51 | * 52 | * @throws ReflectionException 53 | */ 54 | public static function invokeStatic(string $className, string $methodName, ...$args) : mixed{ 55 | if(!isset(self::$methCache[$k = "$className - $methodName"])){ 56 | $refClass = new ReflectionClass($className); 57 | $refMeth = $refClass->getMethod($methodName); 58 | }else{ 59 | $refMeth = self::$methCache[$k]; 60 | } 61 | return $refMeth->invoke(null, ...$args); 62 | } 63 | 64 | /** 65 | * @param mixed ...$args 66 | * 67 | * @throws ReflectionException 68 | */ 69 | public static function invoke(string $className, object $instance, string $methodName, ...$args) : mixed{ 70 | if(!isset(self::$methCache[$k = "$className - $methodName"])){ 71 | $refClass = new ReflectionClass($className); 72 | $refMeth = $refClass->getMethod($methodName); 73 | }else{ 74 | $refMeth = self::$methCache[$k]; 75 | } 76 | return $refMeth->invoke($instance, ...$args); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Supero/NightfallProtocol/utils/Utils.php: -------------------------------------------------------------------------------- 1 | $array 21 | * @phpstan-return \Generator 22 | */ 23 | public static function stringifyKeys(array $array) : \Generator{ 24 | foreach($array as $key => $value){ // @phpstan-ignore-line - this is where we fix the stupid bullshit with array keys :) 25 | yield (string) $key => $value; 26 | } 27 | } 28 | 29 | /** 30 | * Array map implementation that preserves keys. 31 | * 32 | * @phpstan-template TKeyType 33 | * @phpstan-template TValueType 34 | * @phpstan-template TResultType 35 | * @phpstan-param callable(TValueType) : TResultType $callback 36 | * @phpstan-param array $array 37 | * @phpstan-return array 38 | */ 39 | public static function arrayMapPreserveKeys(callable $callback, array $array) : array{ 40 | return array_combine(array_keys($array), array_map($callback, $array)); 41 | } 42 | } 43 | --------------------------------------------------------------------------------