├── .gitignore ├── LICENSE ├── README.md ├── plugin.yml ├── resources ├── chat-scripts.json └── config.yml └── src └── jasonwynn10 └── FakeAdmin ├── Main.php └── network ├── FAInterface.php └── FakeAdmin.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FakeAdmin 2 | A false player using Specter which can interact with real players and manage the server as OP 3 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: FakeAdmin 2 | main: jasonwynn10\FakeAdmin\Main 3 | version: 0.1.0 4 | api: 5 | - 3.0.0-ALPHA5 6 | - 3.0.0-ALPHA6 7 | load: POSTWORLD 8 | depend: 9 | - Specter 10 | softdepend: 11 | - PiggyAuth 12 | - MyAuth 13 | - PurePerms 14 | - AuthMePE 15 | - SimpleAuthHelper 16 | - SimpleAuth 17 | - HereAuth 18 | - LeetAuth -------------------------------------------------------------------------------- /resources/chat-scripts.json: -------------------------------------------------------------------------------- 1 | { 2 | "Received message": "response to received message", 3 | "Who's the owner?": "I'm the owner {%sender}", 4 | "Can I have op?": "No, but you can be banned if you ask again.", 5 | "[HereAuth] Your account data is being loaded. Please wait patiently; it shouldn't take long.": "", 6 | "§bPlease, login using /login ": "/login {%login}", 7 | "§cYou aren't registered yet!": "/register {%login}", 8 | "Please register using: /register ": "/register {%pass}", 9 | "Please log in using: /login ": "/login ", 10 | "Admin come here": [ 11 | "yea sure", 12 | "follow sender" 13 | ] 14 | } -------------------------------------------------------------------------------- /resources/config.yml: -------------------------------------------------------------------------------- 1 | Admin properties: 2 | Name: "FakeAdmin" 3 | Ip: "127.0.0.1" # this can be anything 4 | Port: "58383" # this can be any real port number 5 | # If the server has any authentication systems 6 | authentication: 7 | plugin: "HereAuth" 8 | password: "password" 9 | invisible to non op: false 10 | reply to messages: false 11 | command: true 12 | chat: true 13 | Fake Hacks: false -------------------------------------------------------------------------------- /src/jasonwynn10/FakeAdmin/Main.php: -------------------------------------------------------------------------------- 1 | saveDefaultConfig(); 27 | $this->interface = new FAInterface($this); 28 | $this->getServer()->getNetwork()->registerInterface($this->interface); 29 | $this->getServer()->getPluginManager()->registerEvents($this, $this); 30 | if(!$this->interface->openSession($this->getConfig()->getNested("Admin properties.Name","FakeAdmin"), $this->getConfig()->getNested("Admin properties.Ip","127.0.0.1"), (int)$this->getConfig()->getNested("Admin properties.Port",58383))) { 31 | $this->setEnabled(false); 32 | return; 33 | } 34 | } 35 | 36 | /** 37 | * @param string $str 38 | * @param string $sender 39 | * 40 | * @return mixed|string 41 | */ 42 | public function translate(string $str, string $sender = "") : string { 43 | $str = str_replace("{%name}", $this->getConfig()->getNested("Admin properties.Name","FakeAdmin"), $str); 44 | $str = str_replace("{%login}", $this->getConfig()->getNested("Admin properties.authentication.password",""), $str); 45 | $str = str_replace("{%sender}",$sender, $str); 46 | return $str; 47 | } 48 | 49 | 50 | public function doAI(int $action = self::ACTION_DORMANT, string $target = null) { 51 | /** @var FakeAdmin $fakeAdmin */ 52 | $fakeAdmin = $this->getServer()->getPlayer($this->getConfig()->getNested("Admin properties.Name","FakeAdmin")); 53 | $targetPlayer = $this->getServer()->getPlayer($target ?? $fakeAdmin->target); 54 | if($fakeAdmin->closed || !$fakeAdmin->isAlive()) { 55 | return; 56 | } 57 | if(empty($targetPlayer) && $fakeAdmin->getCurrentAction() !== self::ACTION_DORMANT) { 58 | $fakeAdmin->setAction(self::ACTION_DORMANT); 59 | } elseif(!$targetPlayer->isOnline() && $fakeAdmin->getCurrentAction() !== self::ACTION_DORMANT) { 60 | $fakeAdmin->setAction(self::ACTION_DORMANT); 61 | } 62 | $fakeAdmin->directionFindTick++; 63 | switch($action) { 64 | case self::ACTION_DORMANT: 65 | break; 66 | case self::ACTION_OBSERVE_PLAYER: 67 | $fakeAdmin->generateNewDirection(); 68 | $x = $fakeAdmin->xOffset; 69 | $y = ($fakeAdmin->isFlying() ? $fakeAdmin->yOffset : 0); 70 | $z = $fakeAdmin->zOffset; 71 | if($x * $x + $y * $y + $z * $z < 4) { 72 | $fakeAdmin->motionX = 0; 73 | $fakeAdmin->motionY = 0; 74 | $fakeAdmin->motionZ = 0; 75 | } else { 76 | $fakeAdmin->motionX = $x * $fakeAdmin->getSpeed(); 77 | $fakeAdmin->motionY = 0; 78 | if($y !== $fakeAdmin->y) { 79 | $fakeAdmin->motionY = $y * $fakeAdmin->getSpeed(); 80 | } 81 | $fakeAdmin->motionZ = $z * $fakeAdmin->getSpeed(); 82 | } 83 | if(!$fakeAdmin->isFlying()) { 84 | $fakeAdmin->motionY -= $fakeAdmin->getGravity(); 85 | if($fakeAdmin->isCollidedHorizontally && $fakeAdmin->isOnGround()) { 86 | $fakeAdmin->jump(); 87 | } 88 | } else { 89 | if($fakeAdmin->isCollidedVertically) { 90 | $fakeAdmin->setFlying(false); 91 | } 92 | } 93 | $fakeAdmin->yaw = rad2deg(atan2(-$targetPlayer->x, $targetPlayer->z)); 94 | $fakeAdmin->pitch = rad2deg(-atan2($targetPlayer->getEyeHeight(), sqrt($targetPlayer->x * $targetPlayer->x + $targetPlayer->z * $targetPlayer->z))); 95 | if($targetPlayer->distanceSquared(new Vector3($x, $y, $z)) > 25) { 96 | $fakeAdmin->directionFindTick = 120; 97 | } 98 | $fakeAdmin->move($fakeAdmin->motionX, $fakeAdmin->motionY, $fakeAdmin->motionZ); 99 | $fakeAdmin->checkWalkingArea(); 100 | break; 101 | case self::ACTION_RAPID_SNEAK: 102 | if(mt_rand(0, 5) === 0) { 103 | $fakeAdmin->setSneaking(!$fakeAdmin->isSneaking()); 104 | } 105 | $fakeAdmin->yaw = rad2deg(atan2(-$targetPlayer->x, $targetPlayer->z)); 106 | $fakeAdmin->pitch = rad2deg(-atan2($targetPlayer->getEyeHeight(), sqrt($targetPlayer->x * $targetPlayer->x + $targetPlayer->z * $targetPlayer->z))); 107 | break; 108 | case self::ACTION_ATTACK_TARGET: 109 | if($fakeAdmin->isFlying()) { 110 | $fakeAdmin->setFlying(false); 111 | } 112 | $x = $targetPlayer->x - $fakeAdmin->x; 113 | $z = $targetPlayer->z - $fakeAdmin->z; 114 | if($x * $x + $z * $z < 4) { 115 | $fakeAdmin->motionX = 0; 116 | $fakeAdmin->motionY = 0; 117 | $fakeAdmin->motionZ = 0; 118 | } else { 119 | $fakeAdmin->motionX = $x * $fakeAdmin->getSpeed(); 120 | $fakeAdmin->motionZ = $z * $fakeAdmin->getSpeed(); 121 | } 122 | if($fakeAdmin->isCollidedHorizontally && $fakeAdmin->isOnGround()) { 123 | $fakeAdmin->jump(); 124 | } 125 | $fakeAdmin->yaw = rad2deg(atan2(-$targetPlayer->x, $targetPlayer->z)); 126 | $fakeAdmin->pitch = rad2deg(-atan2($targetPlayer->getEyeHeight(), sqrt($targetPlayer->x * $targetPlayer->x + $targetPlayer->z * $targetPlayer->z))); 127 | $fakeAdmin->hit($targetPlayer); 128 | break; 129 | } 130 | } 131 | 132 | /** 133 | * @priority HIGHEST 134 | * @ignoreCancelled true 135 | * 136 | * @param PlayerPreLoginEvent $ev 137 | */ 138 | public function onPreLogin(PlayerPreLoginEvent $ev) { 139 | if($ev->getPlayer()->getName() === $this->getConfig()->getNested("Admin properties.Name","FakeAdmin")) { 140 | $ev->setCancelled(false); 141 | $ev->getPlayer()->setBanned(false); 142 | $ev->getPlayer()->setGamemode(FakeAdmin::CREATIVE); 143 | if($this->getConfig()->getNested("Admin properties.Fake Hacks", false) !== false) { 144 | $ev->getPlayer()->setAllowFlight(true); 145 | $ev->getPlayer()->setAllowInstaBreak(true); 146 | $ev->getPlayer()->setAllowMovementCheats(true); 147 | $ev->getPlayer()->setCanClimb(true); 148 | $ev->getPlayer()->setCanClimbWalls(true); 149 | } 150 | } 151 | } 152 | 153 | /** 154 | * @priority HIGHEST 155 | * @ignoreCancelled true 156 | * 157 | * @param PlayerLoginEvent $ev 158 | */ 159 | public function onLogin(PlayerLoginEvent $ev) { 160 | if($ev->getPlayer()->getName() === $this->getConfig()->getNested("Admin properties.Name","FakeAdmin")) 161 | $ev->setCancelled(false); 162 | } 163 | 164 | /** 165 | * @priority HIGHEST 166 | * @ignoreCancelled true 167 | * 168 | * @param PlayerJoinEvent $ev 169 | */ 170 | public function onJoin(PlayerJoinEvent $ev) { 171 | if($ev->getPlayer()->getName() !== $this->getConfig()->getNested("Admin properties.Name","FakeAdmin")) 172 | return; 173 | $ev->setCancelled(false); 174 | $ev->getPlayer()->setOp(true); 175 | /** @var PurePerms $pureperms */ 176 | if(($pureperms = $this->getServer()->getPluginManager()->getPlugin("PurePerms")) != null) { 177 | $pureperms->getUserDataMgr()->setPermission($ev->getPlayer(),"*"); 178 | } 179 | } 180 | } -------------------------------------------------------------------------------- /src/jasonwynn10/FakeAdmin/network/FAInterface.php: -------------------------------------------------------------------------------- 1 | plugin = $main; 39 | $this->sessions = new \SplObjectStorage(); 40 | $this->ackStore = []; 41 | $this->replyStore = []; 42 | } 43 | 44 | /** 45 | * Sends a DataPacket to the interface, returns an unique identifier for the packet if $needACK is true 46 | * 47 | * @param Player $player 48 | * @param DataPacket $packet 49 | * @param bool $needACK 50 | * @param bool $immediate 51 | * 52 | * @return int 53 | */ 54 | public function putPacket(Player $player, DataPacket $packet, bool $needACK = false, bool $immediate = true) { 55 | if($player instanceof FakeAdmin) { 56 | switch (get_class($packet)) { 57 | case ResourcePacksInfoPacket::class: 58 | $pk = new ResourcePackClientResponsePacket(); 59 | $pk->status = ResourcePackClientResponsePacket::STATUS_COMPLETED; 60 | $pk->handle($player->getSessionAdapter()); 61 | break; 62 | case TextPacket::class: 63 | /** @var TextPacket $packet */ 64 | switch($packet->type) { 65 | case TextPacket::TYPE_RAW: 66 | /** 67 | * @var string $key 68 | * @var string|string[] $return 69 | */ 70 | foreach(json_decode(file_get_contents($this->plugin->getDataFolder()."chat-scripts.json")) as $received => $return) { 71 | if(similar_text(strtolower($packet->message), strtolower($received)) >= 70) { 72 | if(is_array($return)) { 73 | /** @var string[] $return */ 74 | foreach($return as $ret) { 75 | $ret = $this->plugin->translate($ret); 76 | if(strpos($ret,"/") !== false and $this->plugin->getConfig()->getNested("Admin properties.reply to messages.command", true) === true) { 77 | $pk = new CommandStepPacket(); 78 | $pk->command = substr($ret, 1); 79 | $pk->overload = ""; 80 | $pk->uvarint1 = 0; 81 | $pk->currentStep = 0; 82 | $pk->done = true; 83 | $pk->clientId = $this->getPlayer()->getClientId(); 84 | $pk->inputJson = explode(" ", $ret); 85 | $pk->outputJson = []; 86 | $this->replyStore[$player->getName()][] = $pk; 87 | }elseif($this->plugin->getConfig()->getNested("Admin properties.reply to messages.chat", true)){ 88 | $pk = new TextPacket(); 89 | $pk->type = TextPacket::TYPE_RAW; 90 | $pk->source = $this->getPlayer()->getName(); 91 | $pk->message = $ret; 92 | $this->replyStore[$player->getName()][] = $pk; 93 | } 94 | } 95 | }else{ 96 | /** @var string $return */ 97 | $return = $this->plugin->translate($return, $packet->source); 98 | if($this->getPlayer() != null) { 99 | if(strpos($return,"/") !== false and $this->plugin->getConfig()->getNested("Admin properties.reply to messages.command", true) === true) { 100 | $pk = new CommandStepPacket(); 101 | $pk->command = substr($return, 1); 102 | $pk->overload = ""; 103 | $pk->uvarint1 = 0; 104 | $pk->currentStep = 0; 105 | $pk->done = true; 106 | $pk->clientId = $this->getPlayer()->getClientId(); 107 | $pk->inputJson = explode(" ", $return); 108 | $pk->outputJson = []; 109 | $this->replyStore[$player->getName()][] = $pk; 110 | }elseif($this->plugin->getConfig()->getNested("Admin properties.reply to messages.chat", true)){ 111 | $pk = new TextPacket(); 112 | $pk->type = TextPacket::TYPE_RAW; 113 | $pk->source = $this->getPlayer()->getName(); 114 | $pk->message = $return; 115 | $this->replyStore[$player->getName()][] = $pk; 116 | } 117 | } 118 | } 119 | } 120 | } 121 | break; 122 | case TextPacket::TYPE_CHAT: 123 | /** 124 | * @var string $key 125 | * @var string|string[] $return 126 | */ 127 | foreach(json_decode(file_get_contents($this->plugin->getDataFolder()."chat-scripts.json")) as $received => $return) { 128 | if(similar_text(strtolower($packet->message), strtolower($received)) >= 70) { 129 | if(is_array($return)) { 130 | /** @var string[] $return */ 131 | foreach($return as $ret) { 132 | $ret = $this->plugin->translate($ret); 133 | if(strpos($ret,"/") !== false and $this->plugin->getConfig()->getNested("Admin properties.reply to messages.command", true) === true) { 134 | $pk = new CommandStepPacket(); 135 | $pk->command = substr($ret, 1); 136 | $pk->overload = ""; 137 | $pk->uvarint1 = 0; 138 | $pk->currentStep = 0; 139 | $pk->done = true; 140 | $pk->clientId = $this->getPlayer()->getClientId(); 141 | $pk->inputJson = explode(" ", $ret); 142 | $pk->outputJson = []; 143 | $this->replyStore[$player->getName()][] = $pk; 144 | }elseif($this->plugin->getConfig()->getNested("Admin properties.reply to messages.chat", true)){ 145 | $pk = new TextPacket(); 146 | $pk->type = TextPacket::TYPE_CHAT; 147 | $pk->source = $this->getPlayer()->getName(); 148 | $pk->message = $ret; 149 | $this->replyStore[$player->getName()][] = $pk; 150 | } 151 | } 152 | }else{ 153 | /** @var string $return */ 154 | $return = $this->plugin->translate($return, $packet->source); 155 | if($this->getPlayer() != null) { 156 | if(strpos($return,"/") !== false and $this->plugin->getConfig()->getNested("Admin properties.reply to messages.command", true) === true) { 157 | $pk = new CommandStepPacket(); 158 | $pk->command = substr($return, 1); 159 | $pk->overload = ""; 160 | $pk->uvarint1 = 0; 161 | $pk->currentStep = 0; 162 | $pk->done = true; 163 | $pk->clientId = $this->getPlayer()->getClientId(); 164 | $pk->inputJson = explode(" ", $return); 165 | $pk->outputJson = []; 166 | $this->replyStore[$player->getName()][] = $pk; 167 | }elseif($this->plugin->getConfig()->getNested("Admin properties.reply to messages.chat", true)){ 168 | $pk = new TextPacket(); 169 | $pk->type = TextPacket::TYPE_CHAT; 170 | $pk->source = $this->getPlayer()->getName(); 171 | $pk->message = $return; 172 | $this->replyStore[$player->getName()][] = $pk; 173 | } 174 | } 175 | } 176 | } 177 | } 178 | break; 179 | case TextPacket::TYPE_WHISPER: 180 | /** 181 | * @var string $key 182 | * @var string|string[] $return 183 | */ 184 | foreach(json_decode(file_get_contents($this->plugin->getDataFolder()."chat-scripts.json")) as $received => $return) { 185 | if(similar_text(strtolower($packet->message), strtolower($received)) >= 70) { 186 | if(is_array($return)) { 187 | /** @var string[] $return */ 188 | foreach($return as $ret) { 189 | $ret = $this->plugin->translate($ret); 190 | if(strpos($ret,"/") !== false and $this->plugin->getConfig()->getNested("Admin properties.reply to messages.command", true) === true) { 191 | $pk = new CommandStepPacket(); 192 | $pk->command = substr($ret, 1); 193 | $pk->overload = ""; 194 | $pk->uvarint1 = 0; 195 | $pk->currentStep = 0; 196 | $pk->done = true; 197 | $pk->clientId = $this->getPlayer()->getClientId(); 198 | $pk->inputJson = explode(" ", $ret); 199 | $pk->outputJson = []; 200 | $this->replyStore[$player->getName()][] = $pk; 201 | }elseif($this->plugin->getConfig()->getNested("Admin properties.reply to messages.chat", true)){ 202 | $pk = new TextPacket(); 203 | $pk->type = TextPacket::TYPE_WHISPER; 204 | $pk->source = $this->getPlayer()->getName(); 205 | $pk->message = $ret; 206 | $this->replyStore[$player->getName()][] = $pk; 207 | } 208 | } 209 | }else{ 210 | /** @var string $return */ 211 | $return = $this->plugin->translate($return, $packet->source); 212 | if($this->getPlayer() != null) { 213 | if(strpos($return,"/") !== false and $this->plugin->getConfig()->getNested("Admin properties.reply to messages.command", true) === true) { 214 | $pk = new CommandStepPacket(); 215 | $pk->command = substr($return, 1); 216 | $pk->overload = ""; 217 | $pk->uvarint1 = 0; 218 | $pk->currentStep = 0; 219 | $pk->done = true; 220 | $pk->clientId = $this->getPlayer()->getClientId(); 221 | $pk->inputJson = explode(" ", $return); 222 | $pk->outputJson = []; 223 | $this->replyStore[$player->getName()][] = $pk; 224 | }elseif($this->plugin->getConfig()->getNested("Admin properties.reply to messages.chat", true)){ 225 | $pk = new TextPacket(); 226 | $pk->type = TextPacket::TYPE_WHISPER; 227 | $pk->source = $this->getPlayer()->getName(); 228 | $pk->message = $return; 229 | $this->replyStore[$player->getName()][] = $pk; 230 | } 231 | } 232 | } 233 | } 234 | } 235 | break; 236 | } 237 | break; 238 | case SetHealthPacket::class: 239 | /** @var SetHealthPacket $packet */ 240 | if($packet->health <= 0){ 241 | if($this->plugin->getConfig()->get("autoRespawn")){ 242 | $pk = new RespawnPacket(); 243 | $this->replyStore[$player->getName()][] = $pk; 244 | } 245 | }else{ 246 | $player->spec_needRespawn = true; 247 | } 248 | break; 249 | case StartGamePacket::class: 250 | $pk = new RequestChunkRadiusPacket(); 251 | $pk->radius = 8; 252 | $this->replyStore[$player->getName()][] = $pk; 253 | break; 254 | case PlayStatusPacket::class: 255 | /** @var PlayStatusPacket $packet */ 256 | switch ($packet->status) { 257 | case PlayStatusPacket::PLAYER_SPAWN: 258 | /*$pk = new MovePlayerPacket(); 259 | $pk->x = $player->getPosition()->x; 260 | $pk->y = $player->getPosition()->y; 261 | $pk->z = $player->getPosition()->z; 262 | $pk->yaw = $player->getYaw(); 263 | $pk->pitch = $player->getPitch(); 264 | $pk->bodyYaw = $player->getYaw(); 265 | $pk->onGround = true; 266 | $pk->handle($player);*/ 267 | //TODO 268 | break; 269 | } 270 | break; 271 | case MovePlayerPacket::class: 272 | /** @var MovePlayerPacket $packet */ 273 | $eid = $packet->entityRuntimeId; 274 | if($eid === $player->getId() && $player->isAlive() && $player->spawned === true && $player->getForceMovement() !== null) { 275 | $packet->mode = MovePlayerPacket::MODE_NORMAL; 276 | $packet->yaw += 25; #TODO: revert to old method 277 | $this->replyStore[$player->getName()][] = $packet; 278 | //TODO 279 | } 280 | break; 281 | case BatchPacket::class: 282 | /** @var BatchPacket $packet */ 283 | $packet->decode(); 284 | 285 | foreach($packet->getPackets() as $buf) { 286 | $pk = PacketPool::getPacket($buf); 287 | 288 | if(!$pk->canBeBatched()) { 289 | throw new \InvalidArgumentException("Received invalid " . get_class($pk) . " inside BatchPacket"); 290 | } 291 | 292 | $pk->setBuffer($buf, 1); 293 | $this->putPacket($player, $pk, false, $immediate); 294 | } 295 | break; 296 | } 297 | if($needACK) { 298 | $id = count($this->ackStore[$player->getName()]); 299 | $this->ackStore[$player->getName()][] = $id; 300 | return $id; 301 | } 302 | } 303 | return null; 304 | } 305 | 306 | /** 307 | * Terminates the connection 308 | * 309 | * @param Player $player 310 | * @param string $reason 311 | * 312 | */ 313 | public function close(Player $player, string $reason = "unknown reason") { 314 | $this->sessions->detach($player); 315 | unset($this->ackStore[$player->getName()]); 316 | unset($this->replyStore[$player->getName()]); 317 | } 318 | 319 | /** 320 | * @param string $name 321 | */ 322 | public function setName(string $name) { 323 | // TODO: Implement setName() method. 324 | } 325 | 326 | /** 327 | * @param $username 328 | * @param string $address 329 | * @param int $port 330 | * 331 | * @return bool 332 | */ 333 | public function openSession($username, $address = "127.0.0.1", $port = 58383) { 334 | if(!isset($this->replyStore[$username])) { 335 | $player = new FakeAdmin($this, null, $address, $port); 336 | $this->sessions->attach($player, $username); 337 | $this->ackStore[$username] = []; 338 | $this->replyStore[$username] = []; 339 | $this->plugin->getServer()->addPlayer($username, $player); 340 | 341 | $pk = new class() extends LoginPacket{ 342 | public function decodeAdditional() { 343 | } 344 | }; 345 | $pk->username = $username; 346 | $pk->gameEdition = 0; 347 | $pk->protocol = ProtocolInfo::CURRENT_PROTOCOL; 348 | $pk->clientUUID = UUID::fromData($address, $port, $username)->toString(); 349 | $pk->clientId = 1; 350 | $pk->identityPublicKey = "key here"; 351 | $pk->skin = str_repeat("\x80", 64 * 32 * 4); //TODO: Make this a real skin! 352 | $pk->skinId = "Standard_Alex"; //TODO make this settable with the skin 353 | 354 | $pk->handle($player->getSessionAdapter()); 355 | 356 | return true; 357 | } 358 | else{ 359 | return false; 360 | } 361 | } 362 | 363 | /** 364 | * @return bool 365 | */ 366 | public function process() : bool { 367 | foreach($this->ackStore as $name => $acks) { 368 | $player = $this->plugin->getServer()->getPlayer($name); 369 | if($player instanceof FakeAdmin) { 370 | /** @noinspection PhpUnusedLocalVariableInspection */ 371 | foreach($acks as $id) { 372 | 373 | //$player->handleACK($id); // TODO method removed. Though, plugin shouldn't have ACK to fill. 374 | $this->plugin->getLogger()->debug("Filled ACK."); 375 | } 376 | } 377 | $this->ackStore[$name] = []; 378 | } 379 | /** 380 | * @var string $name 381 | * @var DataPacket[] $packets 382 | */ 383 | foreach($this->replyStore as $name => $packets) { 384 | $player = $this->plugin->getServer()->getPlayer($name); 385 | if($player instanceof FakeAdmin) { 386 | foreach($packets as $pk) { 387 | $pk->handle($player->getSessionAdapter()); 388 | } 389 | } 390 | $this->replyStore[$name] = []; 391 | } 392 | return true; 393 | } 394 | 395 | /** 396 | * @param DataPacket $pk 397 | * @param $player 398 | */ 399 | public function queueReply(DataPacket $pk, $player) { 400 | $this->replyStore[$player][] = $pk; 401 | } 402 | 403 | public function shutdown() { 404 | // TODO: Implement shutdown() method. 405 | } 406 | 407 | public function emergencyShutdown() { 408 | // TODO: Implement emergencyShutdown() method. 409 | } 410 | 411 | /** 412 | * @return FakeAdmin|null 413 | */ 414 | private function getPlayer() { 415 | $p = $this->plugin->getServer()->getPlayer($this->plugin->getConfig()->getNested("Admin properties.Name","FakeAdmin")); 416 | return $p instanceof FakeAdmin ? $p : $p; 417 | } 418 | } -------------------------------------------------------------------------------- /src/jasonwynn10/FakeAdmin/network/FakeAdmin.php: -------------------------------------------------------------------------------- 1 | forceMovement; 39 | } 40 | 41 | /** 42 | * @return PlayerNetworkSessionAdapter 43 | */ 44 | public function getSessionAdapter() { 45 | return $this->sessionAdapter; 46 | } 47 | 48 | public function getCurrentAction() : int { 49 | return $this->currentState; 50 | } 51 | 52 | public function setAction(int $action) { 53 | $this->currentState = $action; 54 | } 55 | 56 | public function getGravity() { 57 | return $this->gravity; 58 | } 59 | 60 | public function generateNewDirection(): bool { 61 | if($this->directionFindTick < 120) { 62 | return false; 63 | } 64 | $this->setSprinting((bool) mt_rand(0, 1)); 65 | $this->flying = (bool) mt_rand(0, 1); 66 | $i = mt_rand(0, 1) === 1 ? 1 : -1; 67 | $this->xOffset = lcg_value() * 7 * $i; 68 | if($this->flying) { 69 | $this->yOffset = lcg_value() * 3 * $i; 70 | } 71 | $this->zOffset = lcg_value() * 7 * $i; 72 | $this->directionFindTick = mt_rand(0, 40); 73 | return true; 74 | } 75 | 76 | public function checkWalkingArea(): bool { 77 | if($this->distance($block = $this->getTargetBlock(2)) <= 1.5) { 78 | if($block instanceof Solid) { 79 | if((int) $block->y === (int) $this->getEyeHeight()) { 80 | $this->directionFindTick = 120; 81 | return true; 82 | } 83 | } 84 | } 85 | return false; 86 | } 87 | 88 | public function getSpeed(): float { 89 | return ($this->isSprinting() ? 0.13 : 0.1); 90 | } 91 | 92 | public function hit(Player $player): bool { 93 | if(($this->isCreative() and $this->distance($player) > 7.5) or ($this->isSurvival() and $this->distance($player) > 5)) { // TODO: Find actual reach length of a player. 94 | return false; 95 | } 96 | if($this->attackDelay < 6) { 97 | $this->attackDelay++; 98 | return false; 99 | } 100 | $player->attack(7, new EntityDamageByEntityEvent($this, $player, EntityDamageEvent::CAUSE_ENTITY_ATTACK, 7)); 101 | $pk = new AnimatePacket(); 102 | $pk->action = 1; 103 | $pk->entityRuntimeId = $this->getId(); 104 | foreach($this->getViewers() as $p) { 105 | $p->dataPacket($pk); 106 | } 107 | return true; 108 | } 109 | } --------------------------------------------------------------------------------