├── .editorconfig
├── .github
└── ISSUE_TEMPLATE.md
├── .gitignore
├── .poggit.yml
├── .travis.yml
├── LICENSE
├── README.md
├── icon.png
├── plugin.yml
├── src
└── slapper
│ ├── Main.php
│ ├── SlapperTrait.php
│ ├── entities
│ ├── SlapperBat.php
│ ├── SlapperBlaze.php
│ ├── SlapperCaveSpider.php
│ ├── SlapperChicken.php
│ ├── SlapperCow.php
│ ├── SlapperCreeper.php
│ ├── SlapperDonkey.php
│ ├── SlapperElderGuardian.php
│ ├── SlapperEnderman.php
│ ├── SlapperEndermite.php
│ ├── SlapperEntity.php
│ ├── SlapperEvoker.php
│ ├── SlapperGhast.php
│ ├── SlapperGuardian.php
│ ├── SlapperHorse.php
│ ├── SlapperHuman.php
│ ├── SlapperHusk.php
│ ├── SlapperIronGolem.php
│ ├── SlapperLavaSlime.php
│ ├── SlapperLlama.php
│ ├── SlapperMule.php
│ ├── SlapperMushroomCow.php
│ ├── SlapperOcelot.php
│ ├── SlapperPig.php
│ ├── SlapperPigZombie.php
│ ├── SlapperPolarBear.php
│ ├── SlapperRabbit.php
│ ├── SlapperSheep.php
│ ├── SlapperShulker.php
│ ├── SlapperSilverfish.php
│ ├── SlapperSkeleton.php
│ ├── SlapperSkeletonHorse.php
│ ├── SlapperSlime.php
│ ├── SlapperSnowman.php
│ ├── SlapperSpider.php
│ ├── SlapperSquid.php
│ ├── SlapperStray.php
│ ├── SlapperVex.php
│ ├── SlapperVillager.php
│ ├── SlapperVindicator.php
│ ├── SlapperWitch.php
│ ├── SlapperWither.php
│ ├── SlapperWitherSkeleton.php
│ ├── SlapperWolf.php
│ ├── SlapperZombie.php
│ ├── SlapperZombieHorse.php
│ ├── SlapperZombieVillager.php
│ └── other
│ │ ├── SlapperBoat.php
│ │ ├── SlapperFallingSand.php
│ │ ├── SlapperMinecart.php
│ │ └── SlapperPrimedTNT.php
│ └── events
│ ├── SlapperCreationEvent.php
│ ├── SlapperDeletionEvent.php
│ └── SlapperHitEvent.php
└── tests
├── ConsoleScript.php
└── travis.sh
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org/
2 | root = yes
3 |
4 | [*]
5 | indent_size = 4
6 | indent_style = tab
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea/
--------------------------------------------------------------------------------
/.poggit.yml:
--------------------------------------------------------------------------------
1 | --- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/jojoe77777/Slapper
2 | branches:
3 | - master
4 | projects:
5 | Slapper:
6 | path: ""
7 | ...
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 7.2
5 |
6 | before_script:
7 | - echo | pecl install channel://pecl.php.net/yaml-2.0.2
8 |
9 | script:
10 | - ./tests/travis.sh
11 |
12 | notifications:
13 | email: false
14 | webhooks: http://melban.com/webhook/discord.php
15 |
--------------------------------------------------------------------------------
/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 | # Slapper
2 |
3 |
4 | The new home of Slapper, the NPC plugin for PocketMine-MP.
5 |
6 | ## NOTE
7 | This plugin is designed for **[PocketMine-MP](https://github.com/pmmp/PocketMine-MP)** only and we do not support any other variations, forks or spoons.
8 | Compatibility with unofficial variants can occasionally be found, but **do not expect support if you are using anything other than PocketMine-MP**.
9 |
10 | ## Addons
11 |
12 | Official addons:
13 | - [SlapBack](https://github.com/jojoe77777/SlapBack)
14 | - [SlapperRotation](https://github.com/jojoe77777/SlapperRotation)
15 | - [SlapperCache](https://github.com/jojoe77777/SlapperCache)
16 | - [SlapperPlus](https://github.com/jojoe77777/SlapperPlus)
17 | - [SlapperCooldown](https://github.com/jojoe77777/SlapperCooldown)
18 |
19 |
20 |
21 | # Basic documentation
22 |
23 | ## Commands:
24 |
25 | - /slapper [args...]
26 | - /rca - Run command as another player! This can be used to only run the command if the player has permission.
27 |
28 | ## Main level commands:
29 | - help: /slapper help
30 | - spawn: /slapper spawn [name]
31 | - edit: /slapper edit [id] [args...]
32 | - id: /slapper id
33 | - remove: /slapper remove [id]
34 | - version: /slapper version
35 | - cancel: /slapper cancel
36 | - updateall: /slapper updateall
37 |
38 | ### Edit args:
39 | - helmet: /slapper edit helmet
40 | - chestplate: /slapper edit
41 | - leggings: /slapper edit leggings
42 | - boots: /slapper edit boots
43 | - skin: /slapper edit skin
44 | - name: /slapper edit name
45 | - addcommand: /slapper edit addcommand
46 | - delcommand: /slapper edit delcommand
47 | - listcommands: /slapper edit listcommands
48 | - update: /slapper edit update
49 | - block: /slapper edit block
50 | - tphere: /slapper edit tphere
51 | - tpto: /slapper edit tpto
52 | - menuname: /slapper edit menuname
53 |
54 |
55 | ### Aliases for edit args
56 | helmet: helm, helmet, head, hat, cap
57 | chestplate: chest, shirt, chestplate
58 | leggings: pants, legs, leggings
59 | boots: feet, boots, shoes
60 | item: hand, item, holding, arm, held
61 | skin: setskin, changeskin, editskin, skin
62 | name: name, customname
63 | menuname: listname, nameonlist, menuname
64 | namevisible: namevisible, customnamevisible, tagvisible, name_visible, custom_name_visible, tag_visible
65 | addcommand: addc, adduced, add command
66 | delcommand: delc, delcmd, delcommand, remove command
67 | listcommands: listcommands, listcmds, listcs
68 | fix: update, fix, migrate
69 | block: block, tile, blockid, tileid
70 | tphere: teleporthere, tphere, movehere, bringer
71 | tpto: teleportto, tpto, goto, teleport, tp
72 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jojoe77777/Slapper/440f9aa853ea42e753d1d5f1cd478bdd1b2cc0cd/icon.png
--------------------------------------------------------------------------------
/plugin.yml:
--------------------------------------------------------------------------------
1 | name: Slapper
2 | author: jojoe77777
3 | version: 1.6.1
4 | description: Slapper, the NPC plugin for PocketMine-MP
5 | main: slapper\Main
6 | api: 3.13.0
7 | mcpe-protocol: [361, 388, 389, 390, 407, 408]
8 | website: https://github.com/jojoe77777/Slapper
9 |
10 | commands:
11 | slapper:
12 | description: Create a Slapper NPC, or edit an existing one!
13 | usage: "/slapper [args]..."
14 | permission: slapper.command
15 | rca:
16 | description: Execute a command as someone else!
17 | usage: "/rca "
18 | permission: slapper.rca
19 | nothing:
20 | description: Do nothing!
21 | usage: "/nothing"
22 | permission: slapper.nothing
23 |
24 | permissions:
25 | slapper:
26 | description: Allow using all Slapper commands
27 | default: op
28 | children:
29 | slapper.command:
30 | description: Allow using /slapper
31 | default: op
32 | slapper.create:
33 | description: Allow using command /slapper create
34 | default: op
35 | slapper.edit:
36 | description: Allow editing Slapper entity data with /slapper edit
37 | default: op
38 | slapper.nothing:
39 | description: Allow doing nothing
40 | default: op
41 | slapper.rca:
42 | description: Allow running commands as other players
43 | default: op
44 | slapper.remove:
45 | description: Allow removing Slapper entities with /slapper remove [id]
46 | default: op
47 | slapper.id:
48 | description: Allow viewing entity ID
49 | default: op
50 | slapper.help:
51 | description: Allow viewing Slapper help page
52 | default: op
53 |
--------------------------------------------------------------------------------
/src/slapper/Main.php:
--------------------------------------------------------------------------------
1 | "LavaSlime",
68 | "ZombiePigman" => "PigZombie",
69 | "Mooshroom" => "MushroomCow",
70 | "Player" => "Human",
71 | "VillagerZombie" => "ZombieVillager",
72 | "SnowGolem" => "Snowman",
73 | "FallingBlock" => "FallingSand",
74 | "FakeBlock" => "FallingSand",
75 | "VillagerGolem" => "IronGolem",
76 | "EGuardian" => "ElderGuardian",
77 | "Emite" => "Endermite"
78 | ];
79 |
80 | /** @var array */
81 | public $hitSessions = [];
82 | /** @var array */
83 | public $idSessions = [];
84 | /** @var string */
85 | public $prefix = TextFormat::GREEN . "[" . TextFormat::YELLOW . "Slapper" . TextFormat::GREEN . "] ";
86 | /** @var string */
87 | public $noperm = TextFormat::GREEN . "[" . TextFormat::YELLOW . "Slapper" . TextFormat::GREEN . "] You don't have permission.";
88 | /** @var string */
89 | public $helpHeader =
90 | TextFormat::YELLOW . "---------- " .
91 | TextFormat::GREEN . "[" . TextFormat::YELLOW . "Slapper Help" . TextFormat::GREEN . "] " .
92 | TextFormat::YELLOW . "----------";
93 |
94 | /** @var string[] */
95 | public $mainArgs = [
96 | "help: /slapper help",
97 | "spawn: /slapper spawn [name]",
98 | "edit: /slapper edit [id] [args...]",
99 | "id: /slapper id",
100 | "remove: /slapper remove [id]",
101 | "version: /slapper version",
102 | "cancel: /slapper cancel",
103 | ];
104 | /** @var string[] */
105 | public $editArgs = [
106 | "helmet: /slapper edit helmet ",
107 | "chestplate: /slapper edit chestplate ",
108 | "leggings: /slapper edit leggings ",
109 | "boots: /slapper edit boots ",
110 | "skin: /slapper edit skin",
111 | "name: /slapper edit name ",
112 | "addcommand: /slapper edit addcommand ",
113 | "delcommand: /slapper edit delcommand ",
114 | "listcommands: /slapper edit listcommands",
115 | "blockid: /slapper edit block ",
116 | "scale: /slapper edit scale ",
117 | "tphere: /slapper edit tphere",
118 | "tpto: /slapper edit tpto",
119 | "menuname: /slapper edit menuname "
120 | ];
121 |
122 | /**
123 | * @return void
124 | */
125 | public function onEnable(): void {
126 | foreach ([
127 | SlapperCreeper::class, SlapperBat::class, SlapperSheep::class,
128 | SlapperPigZombie::class, SlapperGhast::class, SlapperBlaze::class,
129 | SlapperIronGolem::class, SlapperSnowman::class, SlapperOcelot::class,
130 | SlapperZombieVillager::class, SlapperHuman::class, SlapperCow::class,
131 | SlapperZombie::class, SlapperSquid::class, SlapperVillager::class,
132 | SlapperSpider::class, SlapperPig::class, SlapperMushroomCow::class,
133 | SlapperWolf::class, SlapperLavaSlime::class, SlapperSilverfish::class,
134 | SlapperSkeleton::class, SlapperSlime::class, SlapperChicken::class,
135 | SlapperEnderman::class, SlapperCaveSpider::class, SlapperBoat::class,
136 | SlapperMinecart::class, SlapperMule::class, SlapperWitch::class,
137 | SlapperPrimedTNT::class, SlapperHorse::class, SlapperDonkey::class,
138 | SlapperSkeletonHorse::class, SlapperZombieHorse::class, SlapperRabbit::class,
139 | SlapperStray::class, SlapperHusk::class, SlapperWitherSkeleton::class,
140 | SlapperFallingSand::class, SlapperElderGuardian::class, SlapperEndermite::class,
141 | SlapperEvoker::class, SlapperGuardian::class, SlapperLlama::class,
142 | SlapperPolarBear::class, SlapperShulker::class, SlapperVex::class,
143 | SlapperVindicator::class, SlapperWither::class
144 | ] as $className) {
145 | Entity::registerEntity($className, true);
146 | }
147 | $this->getServer()->getPluginManager()->registerEvents($this, $this);
148 | }
149 |
150 | /**
151 | * @param CommandSender $sender
152 | * @param Command $command
153 | * @param string $label
154 | * @param string[] $args
155 | *
156 | * @return bool
157 | */
158 | public function onCommand(CommandSender $sender, Command $command, string $label, array $args): bool {
159 | switch (strtolower($command->getName())) {
160 | case "nothing":
161 | return true;
162 | case "rca":
163 | if (count($args) < 2) {
164 | $sender->sendMessage($this->prefix . "Please enter a player and a command.");
165 | return true;
166 | }
167 | $player = $this->getServer()->getPlayer(array_shift($args));
168 | if ($player instanceof Player) {
169 | $this->getServer()->dispatchCommand($player, trim(implode(" ", $args)));
170 | return true;
171 | } else {
172 | $sender->sendMessage($this->prefix . "Player not found.");
173 | return true;
174 | }
175 | case "slapper":
176 | if ($sender instanceof Player) {
177 | if (!isset($args[0])) {
178 | if (!$sender->hasPermission("slapper.command")) {
179 | $sender->sendMessage($this->noperm);
180 | return true;
181 | } else {
182 | $sender->sendMessage($this->prefix . "Please type '/slapper help'.");
183 | return true;
184 | }
185 | }
186 | $arg = array_shift($args);
187 | switch ($arg) {
188 | case "id":
189 | if (!$sender->hasPermission("slapper.id")) {
190 | $sender->sendMessage($this->noperm);
191 | return true;
192 | }
193 | $this->idSessions[$sender->getName()] = true;
194 | $sender->sendMessage($this->prefix . "Hit an entity to get its ID!");
195 | return true;
196 | case "version":
197 | if (!$sender->hasPermission("slapper.version")) {
198 | $sender->sendMessage($this->noperm);
199 | return true;
200 | }
201 | $desc = $this->getDescription();
202 | $sender->sendMessage($this->prefix . TextFormat::BLUE . $desc->getName() . " " . $desc->getVersion() . " " . TextFormat::GREEN . "by " . TextFormat::GOLD . "jojoe77777");
203 | return true;
204 | case "cancel":
205 | case "stopremove":
206 | case "stopid":
207 | unset($this->hitSessions[$sender->getName()]);
208 | unset($this->idSessions[$sender->getName()]);
209 | $sender->sendMessage($this->prefix . "Cancelled.");
210 | return true;
211 | case "remove":
212 | if (!$sender->hasPermission("slapper.remove")) {
213 | $sender->sendMessage($this->noperm);
214 | return true;
215 | }
216 | if (!isset($args[0])) {
217 | $this->hitSessions[$sender->getName()] = true;
218 | $sender->sendMessage($this->prefix . "Hit an entity to remove it.");
219 | return true;
220 | }
221 | $entity = $sender->getLevel()->getEntity((int) $args[0]);
222 | if ($entity !== null) {
223 | if ($entity instanceof SlapperEntity || $entity instanceof SlapperHuman) {
224 | $this->getServer()->getPluginManager()->callEvent(new SlapperDeletionEvent($entity));
225 | $entity->close();
226 | $sender->sendMessage($this->prefix . "Entity removed.");
227 | } else {
228 | $sender->sendMessage($this->prefix . "That entity is not handled by Slapper.");
229 | }
230 | } else {
231 | $sender->sendMessage($this->prefix . "Entity does not exist.");
232 | }
233 | return true;
234 | case "edit":
235 | if (!$sender->hasPermission("slapper.edit")) {
236 | $sender->sendMessage($this->noperm);
237 | return true;
238 | }
239 | if (isset($args[0])) {
240 | $level = $sender->getLevel();
241 | $entity = $level->getEntity((int) $args[0]);
242 | if ($entity !== null) {
243 | if ($entity instanceof SlapperEntity || $entity instanceof SlapperHuman) {
244 | if (isset($args[1])) {
245 | switch ($args[1]) {
246 | case "helm":
247 | case "helmet":
248 | case "head":
249 | case "hat":
250 | case "cap":
251 | if ($entity instanceof SlapperHuman) {
252 | if (isset($args[2])) {
253 | $entity->getArmorInventory()->setHelmet(Item::fromString($args[2]));
254 | $sender->sendMessage($this->prefix . "Helmet updated.");
255 | } else {
256 | $sender->sendMessage($this->prefix . "Please enter an item ID.");
257 | }
258 | } else {
259 | $sender->sendMessage($this->prefix . "That entity can not wear armor.");
260 | }
261 | return true;
262 | case "chest":
263 | case "shirt":
264 | case "chestplate":
265 | if ($entity instanceof SlapperHuman) {
266 | if (isset($args[2])) {
267 | $entity->getArmorInventory()->setChestplate(Item::fromString($args[2]));
268 | $sender->sendMessage($this->prefix . "Chestplate updated.");
269 | } else {
270 | $sender->sendMessage($this->prefix . "Please enter an item ID.");
271 | }
272 | } else {
273 | $sender->sendMessage($this->prefix . "That entity can not wear armor.");
274 | }
275 | return true;
276 | case "pants":
277 | case "legs":
278 | case "leggings":
279 | if ($entity instanceof SlapperHuman) {
280 | if (isset($args[2])) {
281 | $entity->getArmorInventory()->setLeggings(Item::fromString($args[2]));
282 | $sender->sendMessage($this->prefix . "Leggings updated.");
283 | } else {
284 | $sender->sendMessage($this->prefix . "Please enter an item ID.");
285 | }
286 | } else {
287 | $sender->sendMessage($this->prefix . "That entity can not wear armor.");
288 | }
289 | return true;
290 | case "feet":
291 | case "boots":
292 | case "shoes":
293 | if ($entity instanceof SlapperHuman) {
294 | if (isset($args[2])) {
295 | $entity->getArmorInventory()->setBoots(Item::fromString($args[2]));
296 | $sender->sendMessage($this->prefix . "Boots updated.");
297 | } else {
298 | $sender->sendMessage($this->prefix . "Please enter an item ID.");
299 | }
300 | } else {
301 | $sender->sendMessage($this->prefix . "That entity can not wear armor.");
302 | }
303 | return true;
304 | case "hand":
305 | case "item":
306 | case "holding":
307 | case "arm":
308 | case "held":
309 | if ($entity instanceof SlapperHuman) {
310 | if (isset($args[2])) {
311 | $entity->getInventory()->setItemInHand(Item::fromString($args[2]));
312 | $entity->getInventory()->sendHeldItem($entity->getViewers());
313 | $sender->sendMessage($this->prefix . "Item updated.");
314 | } else {
315 | $sender->sendMessage($this->prefix . "Please enter an item ID.");
316 | }
317 | } else {
318 | $sender->sendMessage($this->prefix . "That entity can not wear armor.");
319 | }
320 | return true;
321 | case "setskin":
322 | case "changeskin":
323 | case "editskin";
324 | case "skin":
325 | if ($entity instanceof SlapperHuman) {
326 | $entity->setSkin($sender->getSkin());
327 | $entity->sendData($entity->getViewers());
328 | $sender->sendMessage($this->prefix . "Skin updated.");
329 | } else {
330 | $sender->sendMessage($this->prefix . "That entity can't have a skin.");
331 | }
332 | return true;
333 | case "name":
334 | case "customname":
335 | if (isset($args[2])) {
336 | array_shift($args);
337 | array_shift($args);
338 | $entity->setNameTag(str_replace(["{color}", "{line}"], ["§", "\n"], trim(implode(" ", $args))));
339 | $entity->sendData($entity->getViewers());
340 | $sender->sendMessage($this->prefix . "Name updated.");
341 | } else {
342 | $sender->sendMessage($this->prefix . "Please enter a name.");
343 | }
344 | return true;
345 | case "listname":
346 | case "nameonlist":
347 | case "menuname":
348 | if ($entity instanceof SlapperHuman) {
349 | if (isset($args[2])) {
350 | $type = 0;
351 | array_shift($args);
352 | array_shift($args);
353 | $input = trim(implode(" ", $args));
354 | switch (strtolower($input)) {
355 | case "remove":
356 | case "":
357 | case "disable":
358 | case "off":
359 | case "hide":
360 | $type = 1;
361 | }
362 | if ($type === 0) {
363 | $entity->namedtag->setString("MenuName", $input);
364 | } else {
365 | $entity->namedtag->setString("MenuName", "");
366 | }
367 | $entity->respawnToAll();
368 | $sender->sendMessage($this->prefix . "Menu name updated.");
369 | } else {
370 | $sender->sendMessage($this->prefix . "Please enter a menu name.");
371 | return true;
372 | }
373 | } else {
374 | $sender->sendMessage($this->prefix . "That entity can not have a menu name.");
375 | }
376 | return true;
377 | case "addc":
378 | case "addcmd":
379 | case "addcommand":
380 | if (isset($args[2])) {
381 | array_shift($args);
382 | array_shift($args);
383 | $input = trim(implode(" ", $args));
384 |
385 | $commands = $entity->namedtag->getCompoundTag("Commands") ?? new CompoundTag("Commands");
386 |
387 | if ($commands->hasTag($input)) {
388 | $sender->sendMessage($this->prefix . "That command has already been added.");
389 | return true;
390 | }
391 | $commands->setString($input, $input);
392 | $entity->namedtag->setTag($commands); //in case a new CompoundTag was created
393 | $sender->sendMessage($this->prefix . "Command added.");
394 | } else {
395 | $sender->sendMessage($this->prefix . "Please enter a command.");
396 | }
397 | return true;
398 | case "delc":
399 | case "delcmd":
400 | case "delcommand":
401 | case "removecommand":
402 | if (isset($args[2])) {
403 | array_shift($args);
404 | array_shift($args);
405 | $input = trim(implode(" ", $args));
406 |
407 | $commands = $entity->namedtag->getCompoundTag("Commands") ?? new CompoundTag("Commands");
408 |
409 | $commands->removeTag($input);
410 | $entity->namedtag->setTag($commands); //in case a new CompoundTag was created
411 | $sender->sendMessage($this->prefix . "Command removed.");
412 | } else {
413 | $sender->sendMessage($this->prefix . "Please enter a command.");
414 | }
415 | return true;
416 | case "listcommands":
417 | case "listcmds":
418 | case "listcs":
419 | $commands = $entity->namedtag->getCompoundTag("Commands");
420 | if ($commands !== null and $commands->getCount() > 0) {
421 | $id = 0;
422 |
423 | /** @var StringTag $stringTag */
424 | foreach ($commands as $stringTag) {
425 | $id++;
426 | $sender->sendMessage(TextFormat::GREEN . "[" . TextFormat::YELLOW . "S" . TextFormat::GREEN . "] " . TextFormat::YELLOW . $id . ". " . TextFormat::GREEN . $stringTag->getValue() . "\n");
427 | }
428 | } else {
429 | $sender->sendMessage($this->prefix . "That entity does not have any commands.");
430 | }
431 | return true;
432 | case "block":
433 | case "tile":
434 | case "blockid":
435 | case "tileid":
436 | if (isset($args[2])) {
437 | if ($entity instanceof SlapperFallingSand) {
438 | $data = explode(":", $args[2]);
439 | //haxx: we shouldn't use toStaticRuntimeId() because it's internal, but there isn't really any better option at the moment
440 | $entity->getDataPropertyManager()->setInt(Entity::DATA_VARIANT, BlockFactory::toStaticRuntimeId((int) ($data[0] ?? 1), (int) ($data[1] ?? 0)));
441 | $entity->sendData($entity->getViewers());
442 | $sender->sendMessage($this->prefix . "Block updated.");
443 | } else {
444 | $sender->sendMessage($this->prefix . "That entity is not a block.");
445 | }
446 | } else {
447 | $sender->sendMessage($this->prefix . "Please enter a value.");
448 | }
449 | return true;
450 | case "teleporthere":
451 | case "tphere":
452 | case "movehere":
453 | case "bringhere":
454 | $entity->teleport($sender);
455 | $sender->sendMessage($this->prefix . "Teleported entity to you.");
456 | $entity->respawnToAll();
457 | return true;
458 | case "teleportto":
459 | case "tpto":
460 | case "goto":
461 | case "teleport":
462 | case "tp":
463 | $sender->teleport($entity);
464 | $sender->sendMessage($this->prefix . "Teleported you to entity.");
465 | return true;
466 | case "scale":
467 | case "size":
468 | if (isset($args[2])) {
469 | $scale = (float) $args[2];
470 | $entity->getDataPropertyManager()->setFloat(Entity::DATA_SCALE, $scale);
471 | $entity->sendData($entity->getViewers());
472 | $sender->sendMessage($this->prefix . "Updated scale.");
473 | } else {
474 | $sender->sendMessage($this->prefix . "Please enter a value.");
475 | }
476 | return true;
477 | default:
478 | $sender->sendMessage($this->prefix . "Unknown command.");
479 | return true;
480 | }
481 | } else {
482 | $sender->sendMessage($this->helpHeader);
483 | foreach ($this->editArgs as $msgArg) {
484 | $sender->sendMessage(str_replace("", $args[0], TextFormat::GREEN . " - " . $msgArg . "\n"));
485 | }
486 | return true;
487 | }
488 | } else {
489 | $sender->sendMessage($this->prefix . "That entity is not handled by Slapper.");
490 | }
491 | } else {
492 | $sender->sendMessage($this->prefix . "Entity does not exist.");
493 | }
494 | return true;
495 | } else {
496 | $sender->sendMessage($this->helpHeader);
497 | foreach ($this->editArgs as $msgArg) {
498 | $sender->sendMessage(TextFormat::GREEN . " - " . $msgArg . "\n");
499 | }
500 | return true;
501 | }
502 | case "help":
503 | case "?":
504 | $sender->sendMessage($this->helpHeader);
505 | foreach ($this->mainArgs as $msgArg) {
506 | $sender->sendMessage(TextFormat::GREEN . " - " . $msgArg . "\n");
507 | }
508 | return true;
509 | case "add":
510 | case "make":
511 | case "create":
512 | case "spawn":
513 | case "apawn":
514 | case "spanw":
515 | if (!$sender->hasPermission("slapper.create")) {
516 | $sender->sendMessage($this->noperm);
517 | return true;
518 | }
519 | $type = array_shift($args);
520 | $name = str_replace(["{color}", "{line}"], ["§", "\n"], trim(implode(" ", $args)));
521 | if ($type === null || empty(trim($type))) {
522 | $sender->sendMessage($this->prefix . "Please enter an entity type.");
523 | return true;
524 | }
525 | if (empty($name)) {
526 | $name = $sender->getDisplayName();
527 | }
528 | $types = self::ENTITY_TYPES;
529 | $aliases = self::ENTITY_ALIASES;
530 | $chosenType = null;
531 | foreach ($types as $t) {
532 | if (strtolower($type) === strtolower($t)) {
533 | $chosenType = $t;
534 | }
535 | }
536 | if ($chosenType === null) {
537 | foreach ($aliases as $alias => $t) {
538 | if (strtolower($type) === strtolower($alias)) {
539 | $chosenType = $t;
540 | }
541 | }
542 | }
543 | if ($chosenType === null) {
544 | $sender->sendMessage($this->prefix . "Invalid entity type.");
545 | return true;
546 | }
547 | $nbt = $this->makeNBT($chosenType, $sender, $name);
548 | /** @var SlapperEntity $entity */
549 | $entity = Entity::createEntity("Slapper" . $chosenType, $sender->getLevel(), $nbt);
550 | $this->getServer()->getPluginManager()->callEvent(new SlapperCreationEvent($entity, "Slapper" . $chosenType, $sender, SlapperCreationEvent::CAUSE_COMMAND));
551 | $entity->spawnToAll();
552 | $sender->sendMessage($this->prefix . $chosenType . " entity spawned with name " . TextFormat::WHITE . "\"" . TextFormat::BLUE . $name . TextFormat::WHITE . "\"" . TextFormat::GREEN . " and entity ID " . TextFormat::BLUE . $entity->getId());
553 | return true;
554 | default:
555 | $sender->sendMessage($this->prefix . "Unknown command. Type '/slapper help' for help.");
556 | return true;
557 | }
558 | } else {
559 | $sender->sendMessage($this->prefix . "This command only works in game.");
560 | return true;
561 | }
562 | }
563 | return true;
564 | }
565 |
566 | /**
567 | * @param string $type
568 | * @param Player $player
569 | * @param string $name
570 | *
571 | * @return CompoundTag
572 | */
573 | private function makeNBT($type, Player $player, string $name): CompoundTag {
574 | $nbt = Entity::createBaseNBT($player, null, $player->getYaw(), $player->getPitch());
575 | $nbt->setShort("Health", 1);
576 | $nbt->setTag(new CompoundTag("Commands", []));
577 | $nbt->setString("MenuName", "");
578 | $nbt->setString("CustomName", $name);
579 | $nbt->setString("SlapperVersion", $this->getDescription()->getVersion());
580 | if ($type === "Human") {
581 | $player->saveNBT();
582 |
583 | $inventoryTag = $player->namedtag->getListTag("Inventory");
584 | assert($inventoryTag !== null);
585 | $nbt->setTag(clone $inventoryTag);
586 |
587 | $skinTag = $player->namedtag->getCompoundTag("Skin");
588 | assert($skinTag !== null);
589 | $nbt->setTag(clone $skinTag);
590 | }
591 | return $nbt;
592 | }
593 |
594 | /**
595 | * @param EntityDamageEvent $event
596 | *
597 | * @ignoreCancelled true
598 | *
599 | * @return void
600 | */
601 | public function onEntityDamage(EntityDamageEvent $event): void {
602 | $entity = $event->getEntity();
603 | if ($entity instanceof SlapperEntity || $entity instanceof SlapperHuman) {
604 | $event->setCancelled(true);
605 | if (!$event instanceof EntityDamageByEntityEvent) {
606 | return;
607 | }
608 | $damager = $event->getDamager();
609 | if (!$damager instanceof Player) {
610 | return;
611 | }
612 | $this->getServer()->getPluginManager()->callEvent($event = new SlapperHitEvent($entity, $damager));
613 | if ($event->isCancelled()) {
614 | return;
615 | }
616 | $damagerName = $damager->getName();
617 | if (isset($this->hitSessions[$damagerName])) {
618 | if ($entity instanceof SlapperHuman) {
619 | $entity->getInventory()->clearAll();
620 | }
621 | $entity->close();
622 | unset($this->hitSessions[$damagerName]);
623 | $damager->sendMessage($this->prefix . "Entity removed.");
624 | return;
625 | }
626 | if (isset($this->idSessions[$damagerName])) {
627 | $damager->sendMessage($this->prefix . "Entity ID: " . $entity->getId());
628 | unset($this->idSessions[$damagerName]);
629 | return;
630 | }
631 |
632 | if (($commands = $entity->namedtag->getCompoundTag("Commands")) !== null) {
633 | $server = $this->getServer();
634 | /** @var StringTag $stringTag */
635 | foreach ($commands as $stringTag) {
636 | $server->dispatchCommand(new ConsoleCommandSender(), str_replace("{player}", '"' . $damagerName . '"', $stringTag->getValue()));
637 | }
638 | }
639 | }
640 | }
641 |
642 | /**
643 | * @param EntitySpawnEvent $ev
644 | *
645 | * @return void
646 | */
647 | public function onEntitySpawn(EntitySpawnEvent $ev): void {
648 | $entity = $ev->getEntity();
649 | if ($entity instanceof SlapperEntity || $entity instanceof SlapperHuman) {
650 | $clearLagg = $this->getServer()->getPluginManager()->getPlugin("ClearLagg");
651 | if ($clearLagg !== null) {
652 | $clearLagg->exemptEntity($entity);
653 | }
654 | }
655 | }
656 |
657 | /**
658 | * @param EntityMotionEvent $event
659 | *
660 | * @return void
661 | */
662 | public function onEntityMotion(EntityMotionEvent $event): void {
663 | $entity = $event->getEntity();
664 | if ($entity instanceof SlapperEntity || $entity instanceof SlapperHuman) {
665 | $event->setCancelled(true);
666 | }
667 | }
668 | }
669 |
--------------------------------------------------------------------------------
/src/slapper/SlapperTrait.php:
--------------------------------------------------------------------------------
1 | setGenericFlag(Entity::DATA_FLAG_IMMOBILE, true);
38 | if (!$this->namedtag->hasTag("Scale", FloatTag::class)) {
39 | $this->namedtag->setFloat("Scale", 1.0, true);
40 | }
41 | $this->getDataPropertyManager()->setFloat(Entity::DATA_SCALE, $this->namedtag->getFloat("Scale"));
42 | }
43 |
44 | public function tryChangeMovement(): void {
45 |
46 | }
47 |
48 | public function sendData($playerList, array $data = null): void {
49 | if(!is_array($playerList)){
50 | $playerList = [$playerList];
51 | }
52 |
53 | foreach($playerList as $p){
54 | $playerData = $data ?? $this->getDataPropertyManager()->getAll();
55 | unset($playerData[self::DATA_NAMETAG]);
56 | $pk = new SetEntityDataPacket();
57 | $pk->entityRuntimeId = $this->getId();
58 | $pk->metadata = $playerData;
59 | $p->dataPacket($pk);
60 |
61 | $this->sendNameTag($p);
62 | }
63 | }
64 |
65 | public function saveSlapperNbt(): void {
66 | $visibility = 0;
67 | if ($this->isNameTagVisible()) {
68 | $visibility = 1;
69 | if ($this->isNameTagAlwaysVisible()) {
70 | $visibility = 2;
71 | }
72 | }
73 | $scale = $this->getDataPropertyManager()->getFloat(Entity::DATA_SCALE);
74 | $this->namedtag->setInt("NameVisibility", $visibility, true);
75 | $this->namedtag->setFloat("Scale", $scale, true);
76 | }
77 |
78 | public function getDisplayName(Player $player): string {
79 | $vars = [
80 | "{name}" => $player->getName(),
81 | "{display_name}" => $player->getName(),
82 | "{nametag}" => $player->getNameTag()
83 | ];
84 | return str_replace(array_keys($vars), array_values($vars), $this->getNameTag());
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/slapper/entities/SlapperBat.php:
--------------------------------------------------------------------------------
1 | setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ELDER, true);
14 | parent::prepareMetadata();
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/slapper/entities/SlapperEnderman.php:
--------------------------------------------------------------------------------
1 | height = static::HEIGHT;
32 | $this->width = $this->width ?? 1; //polyfill
33 | $this->tagId = Entity::$entityCount++;
34 | parent::__construct($level, $nbt);
35 | $this->prepareMetadata();
36 | $this->setNameTagVisible(false);
37 | }
38 |
39 | public function saveNBT(): void {
40 | parent::saveNBT();
41 | $this->saveSlapperNbt();
42 | }
43 |
44 | protected function sendSpawnPacket(Player $player): void {
45 | $pk = new AddEntityPacket();
46 | $pk->entityRuntimeId = $this->getId();
47 | $pk->type = AddEntityPacket::LEGACY_ID_MAP_BC[static::TYPE_ID];
48 | $pk->position = $this->asVector3();
49 | $pk->yaw = $pk->headYaw = $this->yaw;
50 | $pk->pitch = $this->pitch;
51 | $pk->metadata = $this->getDataPropertyManager()->getAll();
52 | unset($pk->metadata[self::DATA_NAMETAG]);
53 |
54 | $player->dataPacket($pk);
55 |
56 | $pk2 = new AddPlayerPacket();
57 | $pk2->entityRuntimeId = $this->tagId;
58 | $pk2->uuid = UUID::fromRandom();
59 | $pk2->username = $this->getDisplayName($player);
60 | $pk2->position = $this->asVector3()->add(0, static::HEIGHT);
61 | $pk2->item = ItemFactory::get(ItemIds::AIR);
62 | $pk2->metadata = [self::DATA_SCALE => [self::DATA_TYPE_FLOAT, 0.0]];
63 |
64 | $player->dataPacket($pk2);
65 | }
66 |
67 | public function sendNameTag(Player $player): void {
68 | $pk = new SetEntityDataPacket();
69 | $pk->entityRuntimeId = $this->tagId;
70 | $pk->metadata = [self::DATA_NAMETAG => [self::DATA_TYPE_STRING, $this->getDisplayName($player)]];
71 | $player->dataPacket($pk);
72 | }
73 |
74 | public function despawnFrom(Player $player, bool $send = true): void {
75 | parent::despawnFrom($player, $send);
76 | $pk = new RemoveEntityPacket();
77 | $pk->entityUniqueId = $this->tagId;
78 | $player->dataPacket($pk);
79 | }
80 |
81 | public function broadcastMovement(bool $teleport = false): void {
82 | if($this->chunk !== null) {
83 | parent::broadcastMovement($teleport);
84 | $pk = new MoveEntityAbsolutePacket();
85 | $pk->entityRuntimeId = $this->tagId;
86 | $pk->position = $this->asVector3()->add(0, static::HEIGHT + 1.62);
87 | $pk->xRot = $pk->yRot = $pk->zRot = 0;
88 |
89 | $this->level->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $pk);
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/slapper/entities/SlapperEvoker.php:
--------------------------------------------------------------------------------
1 | prepareMetadata();
20 | }
21 |
22 | public function saveNBT(): void {
23 | parent::saveNBT();
24 | $this->saveSlapperNbt();
25 | }
26 |
27 | public function sendNameTag(Player $player): void {
28 | $pk = new SetEntityDataPacket();
29 | $pk->entityRuntimeId = $this->getId();
30 | $pk->metadata = [self::DATA_NAMETAG => [self::DATA_TYPE_STRING, $this->getDisplayName($player)]];
31 | $player->dataPacket($pk);
32 | }
33 |
34 | protected function sendSpawnPacket(Player $player): void {
35 | parent::sendSpawnPacket($player);
36 |
37 | if (($menuName = $this->namedtag->getString("MenuName", "", true)) !== "") {
38 | $player->getServer()->updatePlayerListData($this->getUniqueId(), $this->getId(), $menuName, $this->skin, "", [$player]);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/slapper/entities/SlapperHusk.php:
--------------------------------------------------------------------------------
1 | namedtag->hasTag("BlockID", IntTag::class)) {
21 | $this->namedtag->setInt("BlockID", 1, true);
22 | }
23 |
24 | //haxx: we shouldn't use toStaticRuntimeId() because it's internal, but there isn't really any better option at the moment
25 | $this->getDataPropertyManager()->setInt(self::DATA_VARIANT, BlockFactory::toStaticRuntimeId($this->namedtag->getInt("BlockID")));
26 | }
27 |
28 | public function saveNBT(): void {
29 | parent::saveNBT();
30 | $this->namedtag->setInt("BlockID", $this->getDataPropertyManager()->getInt(self::DATA_VARIANT), true);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/slapper/entities/other/SlapperMinecart.php:
--------------------------------------------------------------------------------
1 | entity = $entity;
33 | $this->type = $type;
34 | $this->creator = $creator;
35 | $this->cause = $cause;
36 | }
37 |
38 | public function getEntity(): Entity {
39 | return $this->entity;
40 | }
41 |
42 | public function getCreator(): ?Player {
43 | return $this->creator;
44 | }
45 |
46 | public function hasCreator(): bool {
47 | return $this->creator !== null;
48 | }
49 |
50 | public function getCause(): int {
51 | return $this->cause;
52 | }
53 |
54 | public function getType(): string {
55 | return $this->type;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/slapper/events/SlapperDeletionEvent.php:
--------------------------------------------------------------------------------
1 | entity = $entity;
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/slapper/events/SlapperHitEvent.php:
--------------------------------------------------------------------------------
1 | entity = $entity;
19 | $this->damager = $damager;
20 | }
21 |
22 | /**
23 | * @return Player
24 | */
25 | public function getDamager(): Player {
26 | return $this->damager;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/ConsoleScript.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | */
17 |
18 | const VERSION = "1.11.1";
19 |
20 | $opts = getopt("", ["make:", "relative:", "out:", "entry:", "compress", "stub:"]);
21 |
22 | if(!isset($opts["make"])){
23 | echo "== PocketMine-MP DevTools CLI interface ==\n\n";
24 | echo "Usage: " . PHP_BINARY . " -dphar.readonly=0 " . $argv[0] . " --make --relative --entry \"relativeSourcePath.php\" --out \n";
25 | exit(0);
26 | }
27 |
28 | if(ini_get("phar.readonly") == 1){
29 | echo "Set phar.readonly to 0 with -dphar.readonly=0\n";
30 | exit(1);
31 | }
32 |
33 | $folderPath = rtrim(str_replace("\\", "/", realpath($opts["make"])), "/") . "/";
34 | $relativePath = isset($opts["relative"]) ? rtrim(str_replace("\\", "/", realpath($opts["relative"])), "/") . "/" : $folderPath;
35 | $pharName = $opts["out"] ?? "output.phar";
36 | $stubPath = $opts["stub"] ?? "stub.php";
37 |
38 |
39 | if(!is_dir($folderPath)){
40 | echo $folderPath . " is not a folder\n";
41 | exit(1);
42 | }
43 |
44 | echo "\nCreating " . $pharName . "...\n";
45 | $phar = new \Phar($pharName);
46 |
47 | if(file_exists($relativePath . $stubPath)){
48 | echo "Using stub " . $relativePath . $stubPath . "\n";
49 | $phar->setStub('setStub('setMetadata([
63 | "name" => $metadata["name"],
64 | "version" => $metadata["version"],
65 | "main" => $metadata["main"],
66 | "api" => $metadata["api"],
67 | "depend" => ($metadata["depend"] ?? ""),
68 | "description" => ($metadata["description"] ?? ""),
69 | "authors" => ($metadata["authors"] ?? ""),
70 | "website" => ($metadata["website"] ?? ""),
71 | "creationDate" => time()
72 | ]);
73 |
74 | $phar->setStub('getMetadata() as $key => $value){echo ucfirst($key).": ".(is_array($value) ? implode(", ", $value):$value)."\n";}} __HALT_COMPILER();');
75 | }
76 |
77 | $phar->setSignatureAlgorithm(\Phar::SHA1);
78 | $phar->startBuffering();
79 | echo "Adding files...\n";
80 | $maxLen = 0;
81 | $count = 0;
82 | foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($folderPath)) as $file){
83 | $path = rtrim(str_replace(["\\", $relativePath], ["/", ""], $file), "/");
84 | if($path{0} === "." or strpos($path, "/.") !== false){
85 | continue;
86 | }
87 | $phar->addFile($file, $path);
88 | if(strlen($path) > $maxLen){
89 | $maxLen = strlen($path);
90 | }
91 | echo "\r[" . (++$count) . "] " . str_pad($path, $maxLen, " ");
92 | }
93 |
94 | $phar->stopBuffering();
95 |
96 | echo "\nDone!\n";
97 | exit(0);
--------------------------------------------------------------------------------
/tests/travis.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PHP_BINARY="php"
4 |
5 | while getopts "p:" OPTION 2> /dev/null; do
6 | case ${OPTION} in
7 | p)
8 | PHP_BINARY="$OPTARG"
9 | ;;
10 | esac
11 | done
12 |
13 | "$PHP_BINARY" ./tests/ConsoleScript.php --make . --relative . --out ./Slapper.phar
14 |
15 | if ls Slapper.phar >/dev/null 2>&1; then
16 | echo "Slapper phar created successfully."
17 | echo "Temporary alternate download:"
18 | curl --upload-file ./Slapper.phar https://transfer.sh/Slapper.phar
19 | else
20 | echo "No phar created!"
21 | exit 1
22 | fi
23 |
--------------------------------------------------------------------------------