Advertisement
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

FastTransfer Hack

Comments in 'Plugin Development' started by MrGenga, Nov 16, 2015.

  1. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    Is that good code, what do you think?
    PHP:
    <?php

    /*
     * FastTransfer plugin for PocketMine-MP
     * Copyright (C) 2015 Shoghi Cervantes <https://github.com/shoghicp/FastTransfer>
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     */

    namespace shoghicp\FastTransfer;

    use 
    pocketmine\command\Command;
    use 
    pocketmine\command\CommandSender;
    use 
    pocketmine\event\TranslationContainer;
    use 
    pocketmine\event\player\PlayerRespawnEvent;
    use 
    pocketmine\event\player\PlayerJoinEvent;
    use 
    pocketmine\event\server\DataPacketSendEvent;
    use 
    pocketmine\network\protocol\AdventureSettingsPacket;
    use 
    pocketmine\event\server\DataPacketReceiveEvent;
    use 
    pocketmine\network\protocol\AnimatePacket;
    use 
    pocketmine\network\protocol\BatchPacket;
    use 
    pocketmine\network\protocol\ContainerSetContentPacket;
    use 
    pocketmine\network\protocol\DataPacket;
    use 
    pocketmine\network\protocol\DisconnectPacket;
    use 
    pocketmine\network\protocol\EntityEventPacket;
    use 
    pocketmine\network\protocol\FullChunkDataPacket;
    use 
    pocketmine\network\protocol\Info;
    use 
    pocketmine\network\protocol\PlayStatusPacket;
    use 
    pocketmine\network\protocol\RespawnPacket;
    use 
    pocketmine\network\protocol\TextPacket;
    use 
    pocketmine\network\protocol\MoveEntityPacket;
    use 
    pocketmine\network\protocol\MovePlayerPacket;
    use 
    pocketmine\network\protocol\SetDifficultyPacket;
    use 
    pocketmine\network\protocol\SetEntityMotionPacket;
    use 
    pocketmine\network\protocol\SetHealthPacket;
    use 
    pocketmine\network\protocol\SetSpawnPositionPacket;
    use 
    pocketmine\network\protocol\SetTimePacket;
    use 
    pocketmine\network\protocol\StartGamePacket;
    use 
    pocketmine\network\protocol\TakeItemEntityPacket;
    use 
    pocketmine\network\protocol\UpdateBlockPacket;
    use 
    pocketmine\network\Network;
    use 
    pocketmine\Player;
    use 
    pocketmine\plugin\PluginBase;
    use 
    pocketmine\utils\TextFormat;

    class 
    FastTransfer extends PluginBase{

        private 
    $lookup = [];

        private 
    $transferred = array();

        
    /**
         * Will transfer a connected player to another server.
         * This will trigger PlayerTransferEvent
         *
         * Player transfer might not be instant if you use a DNS address instead of an IP address
         *
         * @param Player $player
         * @param string $address
         * @param int    $port
         * @param string $message If null, ignore message
         *
         * @return bool
         */
        
    public function transferPlayer(Player $player$address$port 19132$message "You are being transferred"){
            
    $ev = new PlayerTransferEvent($player$address$port$message);
            
    $this->getServer()->getPluginManager()->callEvent($ev);
            if(
    $ev->isCancelled()){
                return 
    false;
            }

            
    $ip $this->lookupAddress($ev->getAddress());

            if(
    $ip === null){
                return 
    false;
            }
            
            if(
    $message !== null and $message !== ""){
                
    $player->sendMessage($message);    
            }

            
    $packet = new StrangePacket();
            
    $packet->address $ip;
            
    $packet->port $ev->getPort();
            
    $player->dataPacket($packet->setChannel(Network::CHANNEL_PRIORITY));

            
    $this->transferred[$player->getName()] = $player;

            return 
    true;
        }

        
    /**
         * Clear the DNS lookup cache.
         */
        
    public function cleanLookupCache(){
            
    $this->lookup = [];
        }

        
    /**
         * VERY HARD FastTransfer hack: not fully disconnect player
         */
        
    public function onSend(DataPacketSendEvent $event) {
            if(
    in_array($event->getPlayer(), $this->transferred)){
                
    $event->setCancelled(true);
            }
        }

        
    /**
         * VERY HARD FastTransfer hack: connect player
         */
        
    public function onReceive(DataPacketReceiveEvent $event) {
            if(
    in_array($event->getPlayer(), $this->transferred) && $event->getPacket()->pid() === Info::LOGIN_PACKET){
                
    $event->setCancelled(true);
                
    $pk = new PlayStatusPacket();
                
    $pk->status PlayStatusPacket::LOGIN_SUCCESS;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                
    $spawnPosition $event->getPlayer()->getSpawn();
                
    $pk = new StartGamePacket();
                
    $pk->seed = -1;
                
    $pk->$event->getPlayer()->x;
                
    $pk->$event->getPlayer()->y;
                
    $pk->$event->getPlayer()->z;
                
    $pk->spawnX = (int) $spawnPosition->x;
                
    $pk->spawnY = (int) $spawnPosition->y;
                
    $pk->spawnZ = (int) $spawnPosition->z;
                
    $pk->generator 1//0 old, 1 infinite, 2 flat
                
    $pk->gamemode $event->getPlayer()->getGamemode() & 0x01;
                
    $pk->eid 0;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                
    $pk = new SetTimePacket();
                
    $pk->time $event->getPlayer()->getLevel()->getTime();
                
    $pk->started $event->getPlayer()->getLevel()->stopTime == false;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                
    $pk = new SetSpawnPositionPacket();
                
    $pk->= (int) $spawnPosition->x;
                
    $pk->= (int) $spawnPosition->y;
                
    $pk->= (int) $spawnPosition->z;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                
    $pk = new SetHealthPacket();
                
    $pk->health $event->getPlayer()->getHealth();
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                
    $pk = new SetDifficultyPacket();
                
    $pk->difficulty $this->getServer()->getDifficulty();
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                if(
    $event->getPlayer()->getGaamemode() === Player::SPECTATOR){
                    
    $pk = new ContainerSetContentPacket();
                    
    $pk->windowid ContainerSetContentPacket::SPECIAL_CREATIVE;
                    
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                }else{
                    
    $pk = new ContainerSetContentPacket();
                    
    $pk->windowid ContainerSetContentPacket::SPECIAL_CREATIVE;
                    
    $pk->slots Item::getCreativeItems();
                    
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
                }
                
    $pk = new SetTimePacket();
                
    $pk->time $event->getPlayer()->getLevel->getTime();
                
    $pk->started $event->getPlayer()->getLevel()->stopTime == false;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));

                
    $pos $event->getPlayer()->getLevel()->getSafeSpawn($event->getPlayer());

                
    $this->getServer()->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this$pos));

                
    $pos $ev->getRespawnPosition();

                
    $pk = new RespawnPacket();
                
    $pk->$pos->x;
                
    $pk->$pos->y;
                
    $pk->$pos->z;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_CHUNKS));

                
    $pk = new PlayStatusPacket();
                
    $pk->status PlayStatusPacket::PLAYER_SPAWN;
                
    $event->getPlayer()->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_CHUNKS));

                
    $this->getServer()->getPluginManager()->callEvent($ev = new PlayerJoinEvent($event->getPlayer(),
                    new 
    TranslationContainer(TextFormat::YELLOW "%multiplayer.player.joined", [
                        
    $event->getPlayer()->getDisplayName()
                    ])
                ));
                if(
    strlen(trim($ev->getJoinMessage())) > 0){
                    
    $this->getServer()->broadcastMessage($ev->getJoinMessage());
                }
                unset(
    $this->transferred[$event->getPlayer()->getName()])
            }
        }

        public function 
    onCommand(CommandSender $senderCommand $command$label, array $args){
            if(
    $label === "transfer"){
                if(
    count($args) < or count($args) > or (count($args) === and !($sender instanceof Player))){
                    
    $sender->sendMessage(new TranslationContainer("commands.generic.usage", [$command->getUsage()]));

                    return 
    true;
                }

                
    /** @var Player $target */
                
    $target $sender;

                if(
    count($args) === 3){
                    
    $target $sender->getServer()->getPlayer($args[0]);
                    
    $address $args[1];
                    
    $port = (int) $args[2];
                }else{
                    
    $address $args[0];
                    
    $port = (int) $args[1];
                }

                if(
    $target === null){
                    
    $sender->sendMessage(new TranslationContainer(TextFormat::RED "%commands.generic.player.notFound"));
                    return 
    true;
                }

                
    $sender->sendMessage("Transferring player " $target->getDisplayName() . " to $address:$port");
                if(!
    $this->transferPlayer($target$address$port)){
                    
    $sender->sendMessage(TextFormat::RED "An error occurred during the transfer");
                }

                return 
    true;
            }

            return 
    false;
        }

        
    /**
         * @param $address
         *
         * @return null|string
         */
        
    private function lookupAddress($address){
            
    //IP address
            
    if(preg_match("/^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/"$address) > 0){
                return 
    $address;
            }

            
    $address strtolower($address);

            if(isset(
    $this->lookup[$address])){
                return 
    $this->lookup[$address];
            }

            
    $host gethostbyname($address);
            if(
    $host === $address){
                return 
    null;
            }

            
    $this->lookup[$address] = $host;
            return 
    $host;
        }
    }
  2. deot
    Offline

    deot Active Member Plugin Developer

    Joined:
    Apr 22, 2015
    Posts:
    219
    Plugins:
    1
    Minecraft User:
    deot
    My idea, no, its not... Why you need to use soooo much Packets?... I'm sure that this code is extracted from others server plugin... :p It handles lot of extra (not transfer player required) thing...
    *Correct me if im wrong
    Legoboy0215 likes this.
  3. deot
    Offline

    deot Active Member Plugin Developer

    Joined:
    Apr 22, 2015
    Posts:
    219
    Plugins:
    1
    Minecraft User:
    deot
    And, i dont see u close RakLib session/connection... LOL
  4. deot
    Offline

    deot Active Member Plugin Developer

    Joined:
    Apr 22, 2015
    Posts:
    219
    Plugins:
    1
    Minecraft User:
    deot
    And... there's unused function...
    PHP:
    public function cleanLookupCache(){
            
    $this->lookup = [];
    }
    Hahaha, i can confirm that u 100% copying others code :p and merging it anyway u like xD
  5. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    I
    I think, if I close RakLib, player is disconnect, because closeSession method close player instruction, and close method of Player can kick Player, if it already transferred.
    Packets I extracted from Player.php, from handleDataPacket function
  6. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    It is main class of FastTransfer -_-
  7. deot
    Offline

    deot Active Member Plugin Developer

    Joined:
    Apr 22, 2015
    Posts:
    219
    Plugins:
    1
    Minecraft User:
    deot
    I have no idea why you're doing this... PEMapModder already show us a way to temporary "fix" it by closing RakLib connection...
  8. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    It is not working
  9. deot
    Offline

    deot Active Member Plugin Developer

    Joined:
    Apr 22, 2015
    Posts:
    219
    Plugins:
    1
    Minecraft User:
    deot
    It is... Check my server.. LOL... Yes, its not 100% fixed.. But at least better.. :p There's no permanent/fully working fix of Fasttransfer for PM1.5 (MCPE 0.12.x) Just give it up and look foward to MCPE 0.13.x :p
  10. k3ithkfng
    Offline

    k3ithkfng Active Member

    Joined:
    Jul 9, 2015
    Posts:
    91
    Minecraft User:
    K3ith
    Noob question -
    How do we actually implement this code? Do we just make it into a new plugin and make @MrGenga's or @PEMapModder's code the main class? That's what I'm thinking. What's your answer?
  11. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    If you the cleverest, then give me yout transfer
  12. k3ithkfng
    Offline

    k3ithkfng Active Member

    Joined:
    Jul 9, 2015
    Posts:
    91
    Minecraft User:
    K3ith
    #JustUseTheSearchBar for @PEMapModder's post if you're were smarter :p
    deot likes this.
  13. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    I TRY IT, AN IT NOT WORKS
  14. jojoe77777
    Offline

    jojoe77777 Notable Member Plugin Developer

    Joined:
    May 28, 2015
    Posts:
    653
    Plugins:
    1
    Minecraft User:
    jojoe77777
    That hashtag is getting annoying.
    zombie_Power likes this.
  15. k3ithkfng
    Offline

    k3ithkfng Active Member

    Joined:
    Jul 9, 2015
    Posts:
    91
    Minecraft User:
    K3ith
    Don't tell me, tell @Gamecrafter, the inventor of it :D
  16. Legoboy0215
    Offline

    Legoboy0215 Notable Member

    Joined:
    Nov 1, 2014
    Posts:
    1,724
    Minecraft User:
    Legoboy0215
    Hm... #ReadTheDocs is by me :p #JustUseTheSearchBar is by @Gamecrafter lol
  17. Vaivez66
    Offline

    Vaivez66 Notable Member Plugin Developer

    Joined:
    Jun 10, 2015
    Posts:
    402
    Plugins:
    2
    No, @Gamecrafter is made #UseSearchBar, not #JustUseTheSearchBar xD
  18. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    And it works for me.
    HotFireyDeath likes this.
  19. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    Please give me FULL code, not only closing session part.
  20. MrGenga
    Offline

    MrGenga Active Member

    Joined:
    Jul 24, 2015
    Posts:
    75
    Minecraft User:
    MrGenga
    Why it not works? Player transferred, but not closed from RakLib.
    P.S. Edited FT main class
    PHP:
    <?php

    /*
     * FastTransfer plugin for PocketMine-MP
     * Copyright (C) 2015 Shoghi Cervantes <https://github.com/shoghicp/FastTransfer>
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     */

    namespace shoghicp\FastTransfer;

    use 
    pocketmine\command\Command;
    use 
    pocketmine\command\CommandSender;
    use 
    pocketmine\event\TranslationContainer;
    use 
    pocketmine\network\Network;
    use 
    pocketmine\network\RakLibInterface;
    use 
    pocketmine\Player;
    use 
    pocketmine\plugin\PluginBase;
    use 
    pocketmine\utils\TextFormat;

    class 
    FastTransfer extends PluginBase{

        private 
    $lookup = [];

        
    /**
         * Will transfer a connected player to another server.
         * This will trigger PlayerTransferEvent
         *
         * Player transfer might not be instant if you use a DNS address instead of an IP address
         *
         * @param Player $player
         * @param string $address
         * @param int    $port
         * @param string $message If null, ignore message
         *
         * @return bool
         */
        
    public function transferPlayer(Player $player$address$port 19132$message "You are being transferred"){
            
    $ev = new PlayerTransferEvent($player$address$port$message);
            
    $this->getServer()->getPluginManager()->callEvent($ev);
            if(
    $ev->isCancelled()){
                return 
    false;
            }

            
    $ip $this->lookupAddress($ev->getAddress());

            if(
    $ip === null){
                return 
    false;
            }
            
            if(
    $message !== null and $message !== ""){
                
    $player->sendMessage($message);    
            }

            
    $packet = new StrangePacket();
            
    $packet->address $ip;
            
    $packet->port $ev->getPort();
            
    $player->dataPacket($packet->setChannel(Network::CHANNEL_PRIORITY));
            
    $rakLib null;
            foreach(
    $this->getServer()->getNetwork()-> getInterfaces() as $interface) {
                if(
    $interface instanceof RakLibInterface) {
                    
    $raklib $interface;
                    break;
                }
            }
            if(
    $rakLib == null){
                return 
    false;
            }
            
    $identifier $player ->getAddress () . ":" $player->getPort();
            
    $rakLib->closeSession($identifier"transfer");

            return 
    true;
        }

        
    /**
         * Clear the DNS lookup cache.
         */
        
    public function cleanLookupCache(){
            
    $this->lookup = [];
        }


        public function 
    onCommand(CommandSender $senderCommand $command$label, array $args){
            if(
    $label === "transfer"){
                if(
    count($args) < or count($args) > or (count($args) === and !($sender instanceof Player))){
                    
    $sender->sendMessage(new TranslationContainer("commands.generic.usage", [$command->getUsage()]));

                    return 
    true;
                }

                
    /** @var Player $target */
                
    $target $sender;

                if(
    count($args) === 3){
                    
    $target $sender->getServer()->getPlayer($args[0]);
                    
    $address $args[1];
                    
    $port = (int) $args[2];
                }else{
                    
    $address $args[0];
                    
    $port = (int) $args[1];
                }

                if(
    $target === null){
                    
    $sender->sendMessage(new TranslationContainer(TextFormat::RED "%commands.generic.player.notFound"));
                    return 
    true;
                }

                
    $sender->sendMessage("Transferring player " $target->getDisplayName() . " to $address:$port");
                if(!
    $this->transferPlayer($target$address$port)){
                    
    $sender->sendMessage(TextFormat::RED "An error occurred during the transfer");
                }

                return 
    true;
            }

            return 
    false;
        }

        
    /**
         * @param $address
         *
         * @return null|string
         */
        
    private function lookupAddress($address){
            
    //IP address
            
    if(preg_match("/^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/"$address) > 0){
                return 
    $address;
            }

            
    $address strtolower($address);

            if(isset(
    $this->lookup[$address])){
                return 
    $this->lookup[$address];
            }

            
    $host gethostbyname($address);
            if(
    $host === $address){
                return 
    null;
            }

            
    $this->lookup[$address] = $host;
            return 
    $host;
        }
    }

Share This Page

Advertisement