├── .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 | }
--------------------------------------------------------------------------------