redtv_muqsit/simple-packet-handler

处理特定数据包(用于PMMP API 4.0.0的病毒)

dev-main 2024-09-05 20:03 UTC

This package is not auto-updated.

Last update: 2024-09-20 18:44:29 UTC


README

结束 if-elseif instanceof 的地狱。

API 文档

数据包监控器

监控数据包 - 如果您不修改事件的结果,请使用此功能。
数据包监控器在 MONITOR 优先级上注册 DataPacket(接收/发送)事件。

用例

  • 从数据包中丢弃额外数据
  • 调试数据包是否已发送/接收
/** @var Plugin $plugin */
$packet_monitor = SimplePacketHandler::createMonitor($plugin);

$packet_monitor->monitorIncoming(function(LoginPacket $packet, NetworkSession $origin) : void{
	$this->getLogger()->debug("Received LoginPacket from #" . spl_object_id($origin));
});

$packet_monitor->monitorIncoming(function(ServerSettingsResponsePacket $packet, NetworkSession $origin) : void{
	$this->getLogger()->debug("Received server settings response from {$origin->getPlayer()->getName()}");
});

$packet_monitor->monitorOutgoing(function(SetActorDataPacket $packet, NetworkSession $target) : void{
	$this->getLogger()->debug("Sent SetActorDataPacket to #" . spl_object_id($target));
});

上面提到的 LoginPacket 示例等同于

/**
 * @param DataPacketReceiveEvent $event
 * @priority MONITOR
 */
public function onDataPacketReceive(DataPacketReceiveEvent $event) : void{
	$packet = $event->getPacket();
	if($packet instanceof LoginPacket){
		$origin = $event->getOrigin();
		$this->getLogger()->debug("Received LoginPacket from #" . spl_object_id($origin));
	}
}

上面提到的 SetActorDataPacket 示例等同于

/**
 * @param DataPacketSendEvent $event
 * @priority MONITOR
 */
public function onDataPacketSend(DataPacketSendEvent $event) : void{
	foreach($event->getPackets() as $packet){
		if($packet instanceof SetActorDataPacket){
			foreach($event->getTargets() as $target){
				$this->getLogger()->debug("Sent SetActorDataPacket to #" . spl_object_id($target));
			}
		}
	}
}

数据包拦截器

处理数据包 - 在 MONITOR 优先级上注册 DataPacket(接收/发送)事件。

用例

  • 阻止 pocketmine 处理特定的数据包
  • 在 pocketmine 处理之前修改数据包
/** @var Plugin $plugin */
$packet_interceptor = SimplePacketHandler::createInterceptor($plugin);

$packet_interceptor->interceptIncoming(function(AdventureSettingsPacket $packet, NetworkSession $origin) : bool{
	if($packet->getFlag(AdventureSettingsPacket::FLYING)){
		return false; // cancels the DataPacketReceiveEvent
	}
	return true; // do nothing
});

$packet_interceptor->interceptOutgoing(function(SetTimePacket $packet, NetworkSession $target) : bool{
	$custom_player = CustomPlayerManager::get($target->getPlayer());
	if($custom_player->getPTime() !== $packet->time){
		$target->sendDataPacket(SetTimePacket::create($custom_player->getPTime()));
		return false;
	}
	return true;
});

上面提到的 AdventureSettingsPacket 示例等同于

/**
 * @param DataPacketReceiveEvent $event
 * @priority NORMAL
 */
public function onDataPacketReceive(DataPacketReceiveEvent $event) : void{
	$packet = $event->getPacket();
	if($packet instanceof AdventureSettingsPacket){
		$origin = $event->getOrigin();
		if($packet->getFlag(AdventureSettingsPacket::FLYING)){
			$event->cancel();
		}
	}
}

上面提到的 SetTimePacket 示例等同于

/**
 * @param DataPacketSendEvent $event
 * @priority NORMAL
 */
public function onDataPacketSend(DataPacketSendEvent $event) : void{
	foreach($event->getPackets() as $packet){
		if($packet instanceof SetTimePacket){
			$targets = $event->getTargets();
			$new_targets = $targets;
			foreach($new_targets as $index => $target){
				$custom_player = CustomPlayerManager::get($target->getPlayer());
				if($custom_player->getPTime() !== $packet->time){
					$target->sendDataPacket(SetTimePacket::create($custom_player->getPTime()));
					unset($new_targets[$index]);
				}
			}

			if(count($new_targets) !== count($targets)){
				// Cancel the event, try sending the remaining targets the
				// batch of packets again.
				$event->cancel();
				if(count($new_targets) > 0){
					$new_target_players = [];
					foreach($new_targets as $new_target){
						$new_target_players[] = $new_target->getPlayer();
					}
					$this->getServer()->broadcastPackets($new_target_players, $event->getPackets());
				}
				break;
			}
		}
	}
}