├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
├── java
└── de
│ └── howaner
│ └── FakeMobs
│ ├── FakeMobsPlugin.java
│ ├── adjuster
│ └── MyWorldAccess.java
│ ├── command
│ └── FakeMobCommand.java
│ ├── event
│ ├── PlayerInteractFakeMobEvent.java
│ ├── RemoveFakeMobEvent.java
│ └── SpawnFakeMobEvent.java
│ ├── interact
│ ├── InteractAction.java
│ ├── InteractCommand.java
│ ├── InteractExp.java
│ ├── InteractItem.java
│ ├── InteractText.java
│ └── InteractType.java
│ ├── listener
│ ├── InteractListener.java
│ ├── MobListener.java
│ └── ProtocolListener.java
│ ├── merchant
│ ├── Merchant.java
│ ├── MerchantOffer.java
│ ├── NMSMerchant.java
│ └── ReflectionUtils.java
│ └── util
│ ├── Cache.java
│ ├── Config.java
│ ├── DataWatchCreator.java
│ ├── FakeMob.java
│ ├── ItemParser.java
│ ├── LookUpdate.java
│ ├── MobInventory.java
│ ├── MobShop.java
│ └── SkinQueue.java
└── resources
└── plugin.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binary
2 | bin/
3 |
4 | # Eclipse
5 | .classpath
6 | .project
7 | .settings/
8 |
9 | # Intellij
10 | .idea/
11 | *.iml
12 | *.iws
13 |
14 | # Maven
15 | log/
16 | target/
17 |
18 | # Mac
19 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | FakeMobs
2 | ========
3 |
4 | You can spawn Fake Mobs
5 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | de.howaner
5 | FakeMobs
6 | 1.9.0
7 | FakeMobs
8 | A simple npc plugin
9 | jar
10 |
11 | UTF-8
12 |
13 |
14 |
15 |
16 | spigot-repo
17 | https://hub.spigotmc.org/nexus/content/groups/public/
18 |
19 |
20 | dmulloy2-repo
21 | http://repo.dmulloy2.net/content/groups/public/
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | maven-clean-plugin
30 | 2.5
31 |
32 |
33 | auto-clean
34 | initialize
35 |
36 | clean
37 |
38 |
39 |
40 |
41 |
42 |
43 | org.apache.maven.plugins
44 | maven-compiler-plugin
45 | 2.5.1
46 |
47 | 1.6
48 | 1.6
49 |
50 |
51 |
52 |
53 | org.apache.maven.plugins
54 | maven-jar-plugin
55 | 2.4
56 |
57 | ${project.artifactId}
58 |
59 |
60 |
61 |
62 |
63 |
64 | src/main/resources
65 | true
66 |
67 |
68 |
69 |
70 |
71 |
72 | org.spigotmc
73 | spigot-api
74 | 1.8.3-R0.1-SNAPSHOT
75 |
76 |
77 | com.comphenix.protocol
78 | ProtocolLib
79 | 3.6.4
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/src/main/java/de/howaner/FakeMobs/FakeMobsPlugin.java:
--------------------------------------------------------------------------------
1 | package de.howaner.FakeMobs;
2 |
3 | import com.comphenix.protocol.ProtocolLibrary;
4 | import com.comphenix.protocol.ProtocolManager;
5 | import com.comphenix.protocol.wrappers.WrappedGameProfile;
6 | import com.comphenix.protocol.wrappers.WrappedSignedProperty;
7 | import com.google.common.collect.ArrayListMultimap;
8 | import com.google.common.collect.Multimap;
9 | import de.howaner.FakeMobs.adjuster.MyWorldAccess;
10 | import de.howaner.FakeMobs.command.FakeMobCommand;
11 | import de.howaner.FakeMobs.event.RemoveFakeMobEvent;
12 | import de.howaner.FakeMobs.event.SpawnFakeMobEvent;
13 | import de.howaner.FakeMobs.interact.InteractAction;
14 | import de.howaner.FakeMobs.interact.InteractType;
15 | import de.howaner.FakeMobs.listener.InteractListener;
16 | import de.howaner.FakeMobs.listener.MobListener;
17 | import de.howaner.FakeMobs.listener.ProtocolListener;
18 | import de.howaner.FakeMobs.merchant.MerchantOffer;
19 | import de.howaner.FakeMobs.merchant.ReflectionUtils;
20 | import de.howaner.FakeMobs.util.Cache;
21 | import de.howaner.FakeMobs.util.Config;
22 | import de.howaner.FakeMobs.util.FakeMob;
23 | import de.howaner.FakeMobs.util.LookUpdate;
24 | import de.howaner.FakeMobs.util.MobInventory;
25 | import de.howaner.FakeMobs.util.MobShop;
26 | import de.howaner.FakeMobs.util.SkinQueue;
27 | import java.io.File;
28 | import java.lang.reflect.Field;
29 | import java.util.ArrayList;
30 | import java.util.HashMap;
31 | import java.util.List;
32 | import java.util.Map;
33 | import java.util.Map.Entry;
34 | import java.util.logging.Level;
35 | import java.util.logging.Logger;
36 | import org.bukkit.Bukkit;
37 | import org.bukkit.Chunk;
38 | import org.bukkit.Location;
39 | import org.bukkit.Material;
40 | import org.bukkit.World;
41 | import org.bukkit.configuration.ConfigurationSection;
42 | import org.bukkit.configuration.file.YamlConfiguration;
43 | import org.bukkit.entity.EntityType;
44 | import org.bukkit.entity.Player;
45 | import org.bukkit.plugin.java.JavaPlugin;
46 |
47 | public class FakeMobsPlugin extends JavaPlugin {
48 | public static Logger log;
49 | private static FakeMobsPlugin instance;
50 | private ProtocolManager pManager;
51 | private final Map mobs = new HashMap();
52 | private ProtocolListener pListener;
53 | private SkinQueue skinQueue;
54 |
55 | @Override
56 | public void onEnable() {
57 | instance = this;
58 | log = this.getLogger();
59 | this.pManager = ProtocolLibrary.getProtocolManager();
60 | this.loadMobsFile();
61 |
62 | this.skinQueue = new SkinQueue();
63 | this.skinQueue.start();
64 |
65 | if (!Config.configFile.exists()) Config.save();
66 | Config.load();
67 |
68 | Bukkit.getPluginManager().registerEvents(new InteractListener(), this);
69 | Bukkit.getPluginManager().registerEvents(new MobListener(this), this);
70 | this.getCommand("FakeMob").setExecutor(new FakeMobCommand(this));
71 |
72 | for (Player player : Bukkit.getOnlinePlayers())
73 | this.updatePlayerView(player);
74 |
75 | Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, new LookUpdate(this), 5L, 5L);
76 | this.pManager.addPacketListener(pListener = new ProtocolListener(this));
77 |
78 | for (World world : Bukkit.getWorlds()) {
79 | MyWorldAccess.registerWorldAccess(world);
80 | }
81 |
82 | log.info("Plugin enabled!");
83 | }
84 |
85 | @Override
86 | public void onDisable() {
87 | this.getProtocolManager().removePacketListener(pListener);
88 | Bukkit.getScheduler().cancelTasks(this);
89 | for (FakeMob mob : this.getMobs())
90 | for (Player player : Bukkit.getOnlinePlayers())
91 | if (mob.getWorld() == player.getWorld())
92 | mob.sendDestroyPacket(player);
93 |
94 | for (World world : Bukkit.getWorlds()) {
95 | MyWorldAccess.unregisterWorldAccess(world);
96 | }
97 |
98 | log.info("Plugin disabled!");
99 | }
100 |
101 | public SkinQueue getSkinQueue() {
102 | return this.skinQueue;
103 | }
104 |
105 | public boolean existsMob(int id) {
106 | return this.mobs.containsKey(id);
107 | }
108 |
109 | public FakeMob getMob(Location loc) {
110 | for (FakeMob mob : this.getMobs()) {
111 | if (mob.getLocation().getWorld() == loc.getWorld() &&
112 | mob.getLocation().getBlockX() == loc.getBlockX() &&
113 | mob.getLocation().getBlockY() == loc.getBlockY() &&
114 | mob.getLocation().getBlockZ() == loc.getBlockZ())
115 | return mob;
116 | }
117 | return null;
118 | }
119 |
120 | public boolean isMobOnLocation(Location loc) {
121 | return (this.getMob(loc) != null);
122 | }
123 |
124 | public FakeMob getMob(int id) {
125 | return this.mobs.get(id);
126 | }
127 |
128 | public void removeMob(int id) {
129 | FakeMob mob = this.mobs.get(id);
130 | if (mob == null) return;
131 |
132 | RemoveFakeMobEvent event = new RemoveFakeMobEvent(mob);
133 | Bukkit.getPluginManager().callEvent(event);
134 |
135 | for (Player player : mob.getWorld().getPlayers()) {
136 | mob.unloadPlayer(player);
137 | }
138 |
139 | Map selectedMap = new HashMap();
140 | selectedMap.putAll(Cache.selectedMobs);
141 | for (Entry e : selectedMap.entrySet()) {
142 | if (e.getValue() == mob)
143 | Cache.selectedMobs.remove(e.getKey());
144 | }
145 |
146 | this.mobs.remove(id);
147 | this.saveMobsFile();
148 | }
149 |
150 | public FakeMob spawnMob(Location loc, EntityType type) {
151 | return this.spawnMob(loc, type, null);
152 | }
153 |
154 | public FakeMob spawnMob(Location loc, EntityType type, String customName) {
155 | if (!type.isAlive()) return null;
156 |
157 | int id = this.getNewId();
158 | FakeMob mob = new FakeMob(id, loc, type);
159 | mob.setCustomName(customName);
160 |
161 | SpawnFakeMobEvent event = new SpawnFakeMobEvent(loc, type, mob);
162 | Bukkit.getPluginManager().callEvent(event);
163 | if (event.isCancelled()) return null;
164 |
165 | for (Player player : loc.getWorld().getPlayers()) {
166 | if (mob.isInRange(player)) {
167 | mob.loadPlayer(player);
168 | }
169 | }
170 |
171 | this.mobs.put(id, mob);
172 | this.saveMobsFile();
173 | return mob;
174 | }
175 |
176 | public FakeMob spawnPlayer(Location loc, String name) {
177 | return this.spawnPlayer(loc, name, (Multimap) null);
178 | }
179 |
180 | public FakeMob spawnPlayer(Location loc, String name, Player skin) {
181 | return this.spawnPlayer(loc, name, WrappedGameProfile.fromPlayer(skin).getProperties());
182 | }
183 |
184 | public FakeMob spawnPlayer(Location loc, String name, Multimap skin) {
185 | int id = this.getNewId();
186 | FakeMob mob = new FakeMob(id, loc, EntityType.PLAYER);
187 | mob.setCustomName(name);
188 | mob.setPlayerSkin(skin);
189 |
190 | SpawnFakeMobEvent event = new SpawnFakeMobEvent(loc, EntityType.PLAYER, mob);
191 | Bukkit.getPluginManager().callEvent(event);
192 | if (event.isCancelled()) return null;
193 |
194 | for (Player player : loc.getWorld().getPlayers()) {
195 | if (mob.isInRange(player)) {
196 | mob.loadPlayer(player);
197 | }
198 | }
199 |
200 | this.mobs.put(id, mob);
201 | this.saveMobsFile();
202 | return mob;
203 | }
204 |
205 | public int getNewId() {
206 | int id = -1;
207 | for (FakeMob mob : this.getMobs())
208 | if (mob.getId() > id)
209 | id = mob.getId();
210 | return id+1;
211 | }
212 |
213 | public List getMobs() {
214 | List mobList = new ArrayList();
215 | mobList.addAll(this.mobs.values());
216 | return mobList;
217 | }
218 |
219 | public Map getMobsMap() {
220 | return this.mobs;
221 | }
222 |
223 | /** Called every chunk move */
224 | public void updatePlayerView(Player player) {
225 | for (FakeMob mob : this.getMobs()) {
226 | if (mob.isInRange(player)) {
227 | mob.loadPlayer(player);
228 | } else {
229 | mob.unloadPlayer(player);
230 | }
231 | }
232 | }
233 |
234 | public List getMobsInRadius(Location loc, int radius) {
235 | List mobList = new ArrayList();
236 | for (FakeMob mob : this.getMobs()) {
237 | if (mob.getWorld() == loc.getWorld() && mob.getLocation().distance(loc) <= radius) {
238 | mobList.add(mob);
239 | }
240 | }
241 |
242 | return mobList;
243 | }
244 |
245 | public List getMobsInChunk(World world, int chunkX, int chunkZ) {
246 | List mobList = new ArrayList();
247 |
248 | for (FakeMob mob : this.getMobs()) {
249 | Chunk chunk = mob.getLocation().getChunk();
250 | if (mob.getWorld() == world && chunk.getX() == chunkX && chunk.getZ() == chunkZ) {
251 | mobList.add(mob);
252 | }
253 | }
254 |
255 | return mobList;
256 | }
257 |
258 | public static FakeMobsPlugin getPlugin() {
259 | return instance;
260 | }
261 |
262 | public ProtocolManager getProtocolManager() {
263 | return this.pManager;
264 | }
265 |
266 | public void loadMobsFile() {
267 | this.mobs.clear();
268 | YamlConfiguration config = YamlConfiguration.loadConfiguration(new File("plugins/FakeMobs/mobs.yml"));
269 |
270 | for (String key : config.getKeys(false)) {
271 | ConfigurationSection section = config.getConfigurationSection(key);
272 | int id = Integer.parseInt(key);
273 | Location loc = new Location(Bukkit.getWorld(section.getString("World")),
274 | section.getDouble("X"),
275 | section.getDouble("Y"),
276 | section.getDouble("Z"),
277 | Float.parseFloat(section.getString("Yaw")),
278 | Float.parseFloat(section.getString("Pitch")));
279 | EntityType type = EntityType.valueOf(section.getString("Type").toUpperCase());
280 | FakeMob mob = new FakeMob(id, loc, type);
281 | if (section.isSet("Name") && section.getString("Name").length() <= 16)
282 | mob.setCustomName(section.getString("Name"));
283 | mob.setSitting(section.getBoolean("Sitting"));
284 | if (section.contains("Invisibility"))
285 | mob.setInvisibility(section.getBoolean("Invisibility"));
286 | mob.setPlayerLook(section.getBoolean("PlayerLook"));
287 |
288 | if (section.contains("Inventory")) {
289 | MobInventory inv = new MobInventory();
290 | ConfigurationSection invSection = section.getConfigurationSection("Inventory");
291 | if (invSection.contains("ItemInHand"))
292 | inv.setItemInHand(invSection.getItemStack("ItemInHand"));
293 | if (invSection.contains("Boots"))
294 | inv.setBoots(invSection.getItemStack("Boots"));
295 | if (invSection.contains("Leggings"))
296 | inv.setLeggings(invSection.getItemStack("Leggings"));
297 | if (invSection.contains("ChestPlate"))
298 | inv.setChestPlate(invSection.getItemStack("ChestPlate"));
299 | if (invSection.contains("Helmet"))
300 | inv.setHelmet(invSection.getItemStack("Helmet"));
301 |
302 | mob.setInventory(inv);
303 | }
304 |
305 | if (section.contains("Shop")) {
306 | ConfigurationSection shopSection = section.getConfigurationSection("Shop");
307 | MobShop shop = new MobShop();
308 | for (String key2 : shopSection.getKeys(false)) {
309 | ConfigurationSection itemSection = shopSection.getConfigurationSection(key2);
310 | MerchantOffer offer = new MerchantOffer(itemSection.getItemStack("Item1"),
311 | ((itemSection.contains("Item2")) ? itemSection.getItemStack("Item2") : null),
312 | itemSection.getItemStack("Output"));
313 | shop.addItem(offer);
314 | }
315 | mob.setShop(shop);
316 | }
317 |
318 | if (section.contains("Interacts")) {
319 | ConfigurationSection interactsSection = section.getConfigurationSection("Interacts");
320 | for (String key2 : interactsSection.getKeys(false)) {
321 | ConfigurationSection interactSection = interactsSection.getConfigurationSection(key2);
322 | InteractType interactType = InteractType.getByName(interactSection.getString("Type"));
323 | if (interactType == null) {
324 | log.warning("Interact Type " + interactSection.getString("Type") + " not exists!");
325 | continue;
326 | }
327 | InteractAction action;
328 | try {
329 | action = interactType.getActionClass().newInstance();
330 | } catch (Exception e) {
331 | e.printStackTrace();
332 | continue;
333 | }
334 | action.loadFromConfig(interactSection);
335 | mob.addInteractAction(action);
336 | }
337 | }
338 |
339 | if (mob.getType() == EntityType.PLAYER && section.contains("Skin")) {
340 | ConfigurationSection skinsSection = section.getConfigurationSection("Skin");
341 | Multimap skins = ArrayListMultimap.create();
342 |
343 | for (String k : skinsSection.getKeys(false)) {
344 | ConfigurationSection skinSection = skinsSection.getConfigurationSection(k);
345 | WrappedSignedProperty property = new WrappedSignedProperty(skinSection.getString("Name"), skinSection.getString("Value"), skinSection.getString("Signature"));
346 | skins.put(property.getName(), property);
347 | }
348 |
349 | mob.setPlayerSkin(skins);
350 | }
351 |
352 | this.mobs.put(id, mob);
353 | }
354 |
355 | log.info("Loaded " + this.mobs.size() + " mobs!");
356 | }
357 |
358 | public void saveMobsFile() {
359 | YamlConfiguration config = new YamlConfiguration();
360 |
361 | for (FakeMob mob : this.getMobs()) {
362 | ConfigurationSection section = config.createSection(String.valueOf(mob.getId()));
363 | section.set("World", mob.getWorld().getName());
364 | section.set("X", mob.getLocation().getX());
365 | section.set("Y", mob.getLocation().getY());
366 | section.set("Z", mob.getLocation().getZ());
367 | section.set("Yaw", mob.getLocation().getYaw());
368 | section.set("Pitch", mob.getLocation().getPitch());
369 | section.set("Type", mob.getType().name());
370 | if (mob.getCustomName() != null)
371 | section.set("Name", mob.getCustomName());
372 | section.set("Sitting", mob.isSitting());
373 | section.set("Invisibility", mob.isInvisibility());
374 | section.set("PlayerLook", mob.isPlayerLook());
375 |
376 | if (!mob.getInventory().isEmpty()) {
377 | ConfigurationSection invSection = section.createSection("Inventory");
378 | if (mob.getInventory().getItemInHand() != null && mob.getInventory().getItemInHand().getType() != Material.AIR)
379 | invSection.set("ItemInHand", mob.getInventory().getItemInHand());
380 | if (mob.getInventory().getBoots() != null && mob.getInventory().getBoots().getType() != Material.AIR)
381 | invSection.set("Boots", mob.getInventory().getBoots());
382 | if (mob.getInventory().getLeggings() != null && mob.getInventory().getLeggings().getType() != Material.AIR)
383 | invSection.set("Leggings", mob.getInventory().getLeggings());
384 | if (mob.getInventory().getChestPlate() != null && mob.getInventory().getChestPlate().getType() != Material.AIR)
385 | invSection.set("ChestPlate", mob.getInventory().getChestPlate());
386 | if (mob.getInventory().getHelmet() != null && mob.getInventory().getHelmet().getType() != Material.AIR)
387 | invSection.set("Helmet", mob.getInventory().getHelmet());
388 | }
389 |
390 | if (mob.haveShop()) {
391 | ConfigurationSection shopSection = section.createSection("Shop");
392 | for (int i = 0; i < mob.getShop().getItems().size(); i++) {
393 | ConfigurationSection itemSection = shopSection.createSection(String.valueOf(i));
394 | MerchantOffer offer = mob.getShop().getItems().get(i);
395 | itemSection.set("Item1", offer.getFirstInput());
396 | if (offer.getSecondInput() != null) itemSection.set("Item2", offer.getSecondInput());
397 | itemSection.set("Output", offer.getOutput());
398 | }
399 | }
400 |
401 | if (!mob.getInteractActions().isEmpty()) {
402 | ConfigurationSection interactsSection = section.createSection("Interacts");
403 | for (int i = 0; i < mob.getInteractActions().size(); i++) {
404 | InteractAction action = mob.getInteractActions().get(i);
405 | ConfigurationSection interactSection = interactsSection.createSection("#" + String.valueOf(i));
406 | interactSection.set("Type", action.getType().name());
407 | action.saveToConfig(interactSection);
408 | }
409 | }
410 |
411 | if (mob.getType() == EntityType.PLAYER && mob.getPlayerSkin() != null && !mob.getPlayerSkin().isEmpty()) {
412 | ConfigurationSection skinsSection = section.createSection("Skin");
413 | int i = 0;
414 |
415 | for (WrappedSignedProperty property : mob.getPlayerSkin().values()) {
416 | ConfigurationSection skinSection = skinsSection.createSection("Property-" + String.valueOf(i));
417 | skinSection.set("Name", property.getName());
418 | skinSection.set("Value", property.getValue());
419 | skinSection.set("Signature", property.getSignature());
420 | i++;
421 | }
422 | }
423 | }
424 |
425 | try {
426 | config.save(new File("plugins/FakeMobs/mobs.yml"));
427 | } catch (Exception e) {
428 | e.printStackTrace();
429 | }
430 | }
431 |
432 | public void adjustEntityCount() {
433 | try {
434 | Class entityClass = Class.forName(ReflectionUtils.getNMSPackageName() + ".Entity");
435 |
436 | Field field = entityClass.getDeclaredField("entityCount");
437 | field.setAccessible(true);
438 | int currentCount = field.getInt(null);
439 |
440 | if (currentCount >= 2300) {
441 | while (this.existsMob(currentCount - 2300)) {
442 | currentCount++;
443 | }
444 |
445 | field.set(null, currentCount);
446 | }
447 | } catch (Exception ex) {
448 | this.getLogger().log(Level.WARNING, "Can't adjust entity count", ex);
449 | }
450 | }
451 |
452 | }
453 |
--------------------------------------------------------------------------------
/src/main/java/de/howaner/FakeMobs/adjuster/MyWorldAccess.java:
--------------------------------------------------------------------------------
1 | package de.howaner.FakeMobs.adjuster;
2 |
3 | import de.howaner.FakeMobs.FakeMobsPlugin;
4 | import de.howaner.FakeMobs.merchant.ReflectionUtils;
5 | import java.lang.reflect.Field;
6 | import java.lang.reflect.Method;
7 | import java.lang.reflect.Proxy;
8 | import java.util.Iterator;
9 | import java.util.List;
10 | import java.util.logging.Level;
11 | import org.bukkit.Bukkit;
12 | import org.bukkit.World;
13 |
14 | public class MyWorldAccess implements java.lang.reflect.InvocationHandler {
15 |
16 | @Override
17 | public Object invoke(Object proxy, Method m, Object[] args) {
18 | try {
19 | if (m == null || m.getName() == null) return null;
20 | Class entityClass = Class.forName(ReflectionUtils.getNMSPackageName() + ".Entity");
21 |
22 | if (m.getName().equals("a") && args.length == 1 && args[0] != null && classInstance(args[0].getClass(), entityClass)) {
23 | this.onAddEntity();
24 | }
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | }
28 | return null;
29 | }
30 |
31 | private boolean classInstance(Class clazz, Class instance) {
32 | while (clazz != null) {
33 | if (clazz == instance) {
34 | return true;
35 | }
36 |
37 | clazz = clazz.getSuperclass();
38 | }
39 | return false;
40 | }
41 |
42 | public void onAddEntity() {
43 | FakeMobsPlugin.getPlugin().adjustEntityCount();
44 | }
45 |
46 | private static List getAccessList(World world) throws Exception {
47 | Class craftWorldClass = Class.forName(ReflectionUtils.getOBCPackageName() + ".CraftWorld");
48 | Class worldClass = Class.forName(ReflectionUtils.getNMSPackageName() + ".World");
49 |
50 | Object nmsWorld;
51 | {
52 | Method method = craftWorldClass.getDeclaredMethod("getHandle");
53 | method.setAccessible(true);
54 | nmsWorld = method.invoke(world);
55 | }
56 |
57 | List accessList;
58 | {
59 | Field field = worldClass.getDeclaredField("u");
60 | field.setAccessible(true);
61 | accessList = (List) field.get(nmsWorld);
62 | }
63 |
64 | return accessList;
65 | }
66 |
67 | public static void registerWorldAccess(World world) {
68 | try {
69 | Class iWorldAccessClass = Class.forName(ReflectionUtils.getNMSPackageName() + ".IWorldAccess");
70 | List accessList = getAccessList(world);
71 |
72 | Object myAccess = Proxy.newProxyInstance(Bukkit.class.getClassLoader(), new Class[] { iWorldAccessClass }, new MyWorldAccess());
73 | accessList.add(myAccess);
74 | FakeMobsPlugin.getPlugin().getLogger().log(Level.INFO, "Setted up entity adjuster on world {0}!", world.getName());
75 | } catch (Exception ex) {
76 | FakeMobsPlugin.getPlugin().getLogger().log(Level.WARNING, "Can't register entity adjuster.", ex);
77 | }
78 | }
79 |
80 | public static void unregisterWorldAccess(World world) {
81 | try {
82 | Class iWorldAccessClass = Class.forName(ReflectionUtils.getNMSPackageName() + ".IWorldAccess");
83 | Class proxyClass = Proxy.getProxyClass(Bukkit.class.getClassLoader(), new Class[] { iWorldAccessClass });
84 |
85 | List accessList = getAccessList(world);
86 |
87 | Iterator itr = accessList.iterator();
88 | while (itr.hasNext()) {
89 | if (itr.next().getClass() == proxyClass) {
90 | itr.remove();
91 | FakeMobsPlugin.getPlugin().getLogger().log(Level.INFO, "Removed entity adjuster from world {0}", world.getName());
92 | }
93 | }
94 | } catch (Exception ex) {
95 | FakeMobsPlugin.getPlugin().getLogger().log(Level.WARNING, "Can't unregister entity adjuster.", ex);
96 | }
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/de/howaner/FakeMobs/command/FakeMobCommand.java:
--------------------------------------------------------------------------------
1 | package de.howaner.FakeMobs.command;
2 |
3 | import de.howaner.FakeMobs.FakeMobsPlugin;
4 | import de.howaner.FakeMobs.interact.InteractAction;
5 | import de.howaner.FakeMobs.interact.InteractType;
6 | import de.howaner.FakeMobs.merchant.MerchantOffer;
7 | import de.howaner.FakeMobs.util.Cache;
8 | import de.howaner.FakeMobs.util.FakeMob;
9 | import de.howaner.FakeMobs.util.ItemParser;
10 | import de.howaner.FakeMobs.util.MobShop;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import org.bukkit.ChatColor;
14 | import org.bukkit.Location;
15 | import org.bukkit.command.Command;
16 | import org.bukkit.command.CommandExecutor;
17 | import org.bukkit.command.CommandSender;
18 | import org.bukkit.entity.EntityType;
19 | import org.bukkit.entity.Player;
20 | import org.bukkit.inventory.ItemStack;
21 |
22 | public class FakeMobCommand implements CommandExecutor {
23 | private FakeMobsPlugin plugin;
24 |
25 | public FakeMobCommand(FakeMobsPlugin plugin) {
26 | this.plugin = plugin;
27 | }
28 |
29 | @Override
30 | public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, String[] args) {
31 | if (!(sender instanceof Player)) {
32 | sender.sendMessage(ChatColor.RED + "You are not a Player!");
33 | return true;
34 | }
35 | Player player = (Player) sender;
36 | if (args.length == 0) return false;
37 | if (args[0].equalsIgnoreCase("create")) {
38 | if (args.length != 2) return false;
39 | if (!player.hasPermission("FakeMobs.create")) {
40 | player.sendMessage(ChatColor.RED + "No permission!");
41 | return true;
42 | }
43 | Location loc = player.getLocation();
44 | if (this.plugin.isMobOnLocation(loc)) {
45 | player.sendMessage(ChatColor.RED + "Here is already a Mob!");
46 | return true;
47 | }
48 | EntityType type;
49 | try {
50 | type = EntityType.valueOf(args[1].toUpperCase());
51 | } catch (Exception e) {
52 | player.sendMessage(ChatColor.RED + args[1] + " is not a Entity!");
53 | StringBuilder entityBuilder = new StringBuilder();
54 | boolean komma = false;
55 | for (int i = 0; i < EntityType.values().length; i++) {
56 | EntityType t = EntityType.values()[i];
57 | if (t == null || !t.isAlive() || t.getName() == null) continue;
58 | if (komma) entityBuilder.append(", ");
59 | entityBuilder.append(t.name());
60 | komma = true;
61 | }
62 | player.sendMessage(ChatColor.GOLD + "Available Entitys: " + ChatColor.WHITE + entityBuilder.toString());
63 | return true;
64 | }
65 | if (!type.isAlive()) {
66 | player.sendMessage(ChatColor.RED + "This entity is not alive!");
67 | return true;
68 | }
69 | FakeMob mob = this.plugin.spawnMob(loc, type);
70 | if (mob == null) {
71 | player.sendMessage(ChatColor.RED + "An error occurred while creating the Mob!");
72 | return true;
73 | }
74 | player.sendMessage(ChatColor.GREEN + "Created and selected Mob with ID " + ChatColor.GRAY + "#" + mob.getId());
75 | Cache.selectedMobs.put(player, mob);
76 | return true;
77 | } else if (args[0].equalsIgnoreCase("select")) {
78 | if (args.length != 1 && args.length != 2) return false;
79 | if (!player.hasPermission("FakeMobs.select")) {
80 | player.sendMessage(ChatColor.RED + "No permission!");
81 | return true;
82 | }
83 | if (args.length == 2) {
84 | int id;
85 | try {
86 | id = Integer.valueOf(args[1]);
87 | } catch (Exception e) {
88 | player.sendMessage(ChatColor.RED + "Please enter a valid Id!");
89 | return true;
90 | }
91 | FakeMob mob = this.plugin.getMob(id);
92 | if (mob == null) {
93 | player.sendMessage(ChatColor.RED + "A Mob with ID " + ChatColor.GRAY + "#" + id + ChatColor.RED + " don't exists!");
94 | return true;
95 | }
96 | Cache.selectedMobs.put(player, mob);
97 | player.sendMessage(ChatColor.GREEN + "Mob " + ChatColor.GRAY + "#" + id + ChatColor.GREEN + " selected!");
98 | return true;
99 | }
100 |
101 | if (Cache.selectedMobs.containsKey(player) && Cache.selectedMobs.get(player) == null) {
102 | Cache.selectedMobs.remove(player);
103 | player.sendMessage(ChatColor.GOLD + "Selection cancelled!");
104 | } else {
105 | Cache.selectedMobs.put(player, null);
106 | player.sendMessage(ChatColor.GREEN + "Click on the FakeMob!");
107 | }
108 | return true;
109 | } else if (args[0].equalsIgnoreCase("name")) {
110 | if (args.length < 2) return false;
111 | if (!player.hasPermission("FakeMobs.name")) {
112 | player.sendMessage(ChatColor.RED + "No permission!");
113 | return true;
114 | }
115 | FakeMob mob = Cache.selectedMobs.get(player);
116 | if (mob == null) {
117 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
118 | return true;
119 | }
120 | StringBuilder textBuilder = new StringBuilder();
121 | for (int i = 1; i < args.length; i++) {
122 | if (i != 1) textBuilder.append(" ");
123 | textBuilder.append(args[i]);
124 | }
125 | String text = ChatColor.translateAlternateColorCodes('&', textBuilder.toString());
126 | if (text.length() > 32) {
127 | player.sendMessage(ChatColor.RED + "Name too long!");
128 | return true;
129 | }
130 | if (text.equalsIgnoreCase("none")) {
131 | mob.setCustomName(null);
132 | player.sendMessage(ChatColor.GREEN + "Mob Name deleted!");
133 | } else {
134 | mob.setCustomName(text);
135 | player.sendMessage(ChatColor.GREEN + "Mob Name set to " + ChatColor.GRAY + text + ChatColor.GREEN + "!");
136 | }
137 | mob.updateCustomName();
138 | this.plugin.saveMobsFile();
139 | return true;
140 | } else if (args[0].equalsIgnoreCase("sitting")) {
141 | if (args.length < 1) return false;
142 | if (!player.hasPermission("FakeMobs.sitting")) {
143 | player.sendMessage(ChatColor.RED + "No permission!");
144 | return true;
145 | }
146 | FakeMob mob = Cache.selectedMobs.get(player);
147 | if (mob == null) {
148 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
149 | return true;
150 | }
151 | if (mob.getType() != EntityType.OCELOT && mob.getType() != EntityType.WOLF && mob.getType() != EntityType.PLAYER) {
152 | player.sendMessage(ChatColor.RED + "Only pets and players can sit!");
153 | return true;
154 | }
155 | mob.setSitting(!mob.isSitting());
156 | mob.updateMetadata();
157 | this.plugin.saveMobsFile();
158 | player.sendMessage(ChatColor.GREEN + "Sitting Status changed: " + ChatColor.GRAY + ((mob.isSitting()) ? "on" : "off"));
159 | return true;
160 | } else if (args[0].equalsIgnoreCase("invisibility")) {
161 | if (args.length < 1) return false;
162 | if (!player.hasPermission("FakeMobs.invisibility")) {
163 | player.sendMessage(ChatColor.RED + "No permission!");
164 | return true;
165 | }
166 | FakeMob mob = Cache.selectedMobs.get(player);
167 | if (mob == null) {
168 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
169 | return true;
170 | }
171 | mob.setInvisibility(!mob.isInvisibility());
172 | mob.updateMetadata();
173 | this.plugin.saveMobsFile();
174 | player.sendMessage(ChatColor.GREEN + "Invisibility Status changed: " + ChatColor.GRAY + ((mob.isInvisibility()) ? "on" : "off"));
175 | return true;
176 | } else if (args[0].equalsIgnoreCase("look")) {
177 | if (args.length < 1) return false;
178 | if (!player.hasPermission("FakeMobs.look")) {
179 | player.sendMessage(ChatColor.RED + "No permission!");
180 | return true;
181 | }
182 | FakeMob mob = Cache.selectedMobs.get(player);
183 | if (mob == null) {
184 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
185 | return true;
186 | }
187 | mob.setPlayerLook(!mob.isPlayerLook());
188 | if (mob.isPlayerLook())
189 | mob.sendLookPacket(player, player.getLocation());
190 | this.plugin.saveMobsFile();
191 | player.sendMessage(ChatColor.GREEN + "Player Look: " + ChatColor.GRAY + ((mob.isPlayerLook()) ? "on" : "off"));
192 | return true;
193 | } else if (args[0].equalsIgnoreCase("teleport")) {
194 | if (args.length != 1) return false;
195 | if (!player.hasPermission("FakeMobs.teleport")) {
196 | player.sendMessage(ChatColor.RED + "No permission!");
197 | return true;
198 | }
199 | FakeMob mob = Cache.selectedMobs.get(player);
200 | if (mob == null) {
201 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
202 | return true;
203 | }
204 | mob.teleport(player.getLocation());
205 | this.plugin.saveMobsFile();
206 | player.sendMessage(ChatColor.GREEN + "Teleported Mob " + ChatColor.GRAY + "#" + mob.getId() + ChatColor.GREEN + "!");
207 | return true;
208 | } else if (args[0].equalsIgnoreCase("skin")) {
209 | if (args.length != 2) return false;
210 | if (!player.hasPermission("FakeMobs.skin")) {
211 | player.sendMessage(ChatColor.RED + "No permission!");
212 | return true;
213 | }
214 |
215 | FakeMob mob = Cache.selectedMobs.get(player);
216 | if (mob == null) {
217 | player.sendMessage(ChatColor.RED + "You don't have a selection!");
218 | return true;
219 | }
220 | if (mob.getType() != EntityType.PLAYER) {
221 | player.sendMessage(ChatColor.RED + "Only players can have a skin!");
222 | return true;
223 | }
224 |
225 | FakeMobsPlugin.getPlugin().getSkinQueue().addToQueue(mob, args[1]);
226 | player.sendMessage(ChatColor.GREEN + "Skin set!");
227 | return true;
228 | } else if (args[0].equalsIgnoreCase("inv")) {
229 | if (args.length < 3) return false;
230 | if (!player.hasPermission("FakeMobs.inv")) {
231 | player.sendMessage(ChatColor.RED + "No permission!");
232 | return true;
233 | }
234 | FakeMob mob = Cache.selectedMobs.get(player);
235 | if (mob == null) {
236 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
237 | return true;
238 | }
239 |
240 | List itemArgs = new ArrayList();
241 | for (int i = 2; i < args.length; i++)
242 | itemArgs.add(args[i]);
243 |
244 | ItemStack item;
245 | try {
246 | item = ItemParser.generateItemStack(itemArgs.toArray(new String[0]));
247 | } catch (Exception e) {
248 | player.sendMessage(ChatColor.RED + "Invalid item: " + e.getMessage());
249 | return true;
250 | }
251 |
252 | if (args[1].equalsIgnoreCase("hand")) {
253 | mob.getInventory().setItemInHand(item);
254 | player.sendMessage(ChatColor.GOLD + "Setted Item in Hand to " + item.getType().name() + "!");
255 | } else if (args[1].equalsIgnoreCase("boots")) {
256 | mob.getInventory().setBoots(item);
257 | player.sendMessage(ChatColor.GOLD + "Setted Boots to " + item.getType().name() + "!");
258 | } else if (args[1].equalsIgnoreCase("leggings")) {
259 | mob.getInventory().setLeggings(item);
260 | player.sendMessage(ChatColor.GOLD + "Setted Leggings to " + item.getType().name() + "!");
261 | } else if (args[1].equalsIgnoreCase("chestplate")) {
262 | mob.getInventory().setChestPlate(item);
263 | player.sendMessage(ChatColor.GOLD + "Setted ChestPlate to " + item.getType().name() + "!");
264 | } else if (args[1].equalsIgnoreCase("helmet")) {
265 | mob.getInventory().setHelmet(item);
266 | player.sendMessage(ChatColor.GOLD + "Setted Helmet to " + item.getType().name() + "!");
267 | } else
268 | return false;
269 |
270 | mob.updateInventory();
271 | this.plugin.saveMobsFile();
272 | return true;
273 | } else if (args[0].equalsIgnoreCase("shop")) {
274 | if (args.length < 2) return false;
275 | if (!player.hasPermission("FakeMobs.shop")) {
276 | player.sendMessage(ChatColor.RED + "No permission!");
277 | return true;
278 | }
279 | FakeMob mob = Cache.selectedMobs.get(player);
280 | if (mob == null) {
281 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
282 | return true;
283 | }
284 | if (args[1].equalsIgnoreCase("enable")) {
285 | if (args.length != 2) return false;
286 | if (mob.haveShop()) {
287 | player.sendMessage(ChatColor.RED + "This Mob have already a Shop!");
288 | return true;
289 | }
290 | mob.setShop(new MobShop());
291 | this.plugin.saveMobsFile();
292 | player.sendMessage(ChatColor.GREEN + "Villager Shop enabled!");
293 | return true;
294 | } else if (args[1].equalsIgnoreCase("disable")) {
295 | if (args.length != 2) return false;
296 | if (!mob.haveShop()) {
297 | player.sendMessage(ChatColor.RED + "This Mob haven't a Shop!");
298 | return true;
299 | }
300 | mob.setShop(null);
301 | this.plugin.saveMobsFile();
302 | player.sendMessage(ChatColor.GREEN + "Villager Shop removed!");
303 | return true;
304 | } else if (args[1].equalsIgnoreCase("addItem")) {
305 | if (args.length < 3) return false;
306 | if (!mob.haveShop()) {
307 | player.sendMessage(ChatColor.RED + "This Mob haven't a Shop!");
308 | return true;
309 | }
310 |
311 | StringBuilder builder = new StringBuilder();
312 | for (int i = 2; i < args.length; i++) {
313 | if (i != 2) builder.append(" ");
314 | builder.append(args[i]);
315 | }
316 |
317 | String[] items = builder.toString().split(";");
318 | if (items.length != 2 && args.length != 3) return false;
319 |
320 | String state = "input";
321 | ItemStack item1, item2 = null, result;
322 | try {
323 | item1 = ItemParser.generateItemStack(items[0].split(" "));
324 |
325 | if (items.length == 2) {
326 | state = "result";
327 | result = ItemParser.generateItemStack(items[1].split(" "));
328 | } else {
329 | state = "second input";
330 | item2 = ItemParser.generateItemStack(items[1].split(" "));
331 |
332 | state = "result";
333 | result = ItemParser.generateItemStack(items[2].split(" "));
334 | }
335 | } catch (Exception e) {
336 | player.sendMessage(ChatColor.RED + "Invalid " + state + ": " + e.getMessage());
337 | return true;
338 | }
339 |
340 | MerchantOffer offer = new MerchantOffer(item1, item2, result);
341 | mob.getShop().addItem(offer);
342 | this.plugin.saveMobsFile();
343 | player.sendMessage(ChatColor.GREEN + "Item added!");
344 | return true;
345 | } else if (args[1].equalsIgnoreCase("removeItem")) {
346 | if (args.length != 3) return false;
347 | if (!mob.haveShop()) {
348 | player.sendMessage(ChatColor.RED + "This Mob haven't a Shop!");
349 | return true;
350 | }
351 | int id;
352 | try {
353 | id = Integer.parseInt(args[2]);
354 | } catch (Exception e) {
355 | player.sendMessage(ChatColor.RED + args[2] + " isn't a Id!");
356 | return true;
357 | }
358 | if (mob.getShop().getItem(id) == null) {
359 | player.sendMessage(ChatColor.RED + "Item " + ChatColor.GRAY + "#" + id + ChatColor.RED + " dont't exists!");
360 | return true;
361 | }
362 | mob.getShop().removeItem(id);
363 | this.plugin.saveMobsFile();
364 | player.sendMessage(ChatColor.GOLD + "Item " + ChatColor.GRAY + "#" + id + ChatColor.GOLD + " was removed!");
365 | return true;
366 | } else if (args[1].equalsIgnoreCase("clear")) {
367 | if (args.length != 2) return false;
368 | if (!mob.haveShop()) {
369 | player.sendMessage(ChatColor.RED + "This Mob haven't a Shop!");
370 | return true;
371 | }
372 | if (mob.getShop().getItems().isEmpty()) {
373 | player.sendMessage(ChatColor.RED + "This Shop has no Items!");
374 | return true;
375 | }
376 | mob.getShop().clear();
377 | this.plugin.saveMobsFile();
378 | player.sendMessage(ChatColor.GREEN + "Shop cleared!");
379 | return true;
380 | } else if (args[1].equalsIgnoreCase("items")) {
381 | if (args.length != 2) return false;
382 | if (!mob.haveShop()) {
383 | player.sendMessage(ChatColor.RED + "This Mob haven't a Shop!");
384 | return true;
385 | }
386 | if (mob.getShop().getItems().isEmpty()) {
387 | player.sendMessage(ChatColor.RED + "This Shop has no Items!");
388 | return true;
389 | }
390 | player.sendMessage(ChatColor.GOLD + "Items (" + mob.getShop().getItems().size() + ")");
391 | for (int i = 0; i < mob.getShop().getItems().size(); i++) {
392 | MerchantOffer offer = mob.getShop().getItems().get(i);
393 | StringBuilder builder = new StringBuilder();
394 | builder.append(ChatColor.GRAY);
395 | builder.append(i);
396 | builder.append(". ");
397 | builder.append(ChatColor.WHITE);
398 | //Item 1
399 | builder.append("Item 1: ");
400 | builder.append(offer.getFirstInput().getType().name());
401 | builder.append(" (");
402 | builder.append(offer.getFirstInput().getAmount());
403 | builder.append(")");
404 | //Item 2
405 | builder.append(", Item 2: ");
406 | if (offer.getSecondInput() != null) {
407 | builder.append(offer.getSecondInput().getType().name());
408 | builder.append(" (");
409 | builder.append(offer.getSecondInput().getAmount());
410 | builder.append(")");
411 | } else
412 | builder.append("none");
413 | //Output
414 | builder.append(", Output: ");
415 | builder.append(offer.getOutput().getType().name());
416 | builder.append(" (");
417 | builder.append(offer.getOutput().getAmount());
418 | builder.append(")");
419 |
420 | player.sendMessage(builder.toString());
421 | }
422 | return true;
423 | } else
424 | return false;
425 | } else if (args[0].equalsIgnoreCase("interact")) {
426 | if (args.length < 2)
427 | return false;
428 | if (!player.hasPermission("FakeMobs.interact")) {
429 | player.sendMessage(ChatColor.RED + "No permission!");
430 | return true;
431 | }
432 | FakeMob mob = Cache.selectedMobs.get(player);
433 | if (mob == null) {
434 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
435 | return true;
436 | }
437 | if (args[1].equalsIgnoreCase("add")) {
438 | if (args.length < 4)
439 | return false;
440 | InteractType type = InteractType.getByName(args[2]);
441 | if (type == null) {
442 | player.sendMessage(ChatColor.RED + "Interact type " + args[2] + " can't found!");
443 | player.sendMessage(ChatColor.GREEN + "Available Types: " + ChatColor.WHITE + InteractType.getStringList());
444 | return true;
445 | }
446 | InteractAction action;
447 | try {
448 | action = type.getActionClass().newInstance();
449 | } catch (Exception e) {
450 | e.printStackTrace();
451 | return true;
452 | }
453 | if (action.getArgsLength() != -1 && (args.length - 3) != action.getArgsLength()) {
454 | player.sendMessage(action.getUsageText());
455 | }
456 |
457 | StringBuilder argsBuilder = new StringBuilder();
458 | for (int i = 3; i < args.length; i++) {
459 | if (i != 3) argsBuilder.append(" ");
460 | argsBuilder.append(args[i]);
461 | }
462 |
463 | action.onSet(player, argsBuilder.toString());
464 | mob.addInteractAction(action);
465 | this.plugin.saveMobsFile();
466 | return true;
467 | } else if (args[1].equalsIgnoreCase("remove")) {
468 | if (args.length != 3)
469 | return false;
470 | int id;
471 | try {
472 | id = Integer.parseInt(args[2]);
473 | } catch (Exception e) {
474 | player.sendMessage(ChatColor.RED + args[2] + " isn't a valid ID!");
475 | return true;
476 | }
477 | InteractAction action = mob.getInteractActions().get(id);
478 | if (action == null) {
479 | player.sendMessage(ChatColor.RED + "The Mob haven't a Mob Action with ID #" + id + "!");
480 | return true;
481 | }
482 |
483 | mob.removeInteractAction(action);
484 | player.sendMessage(ChatColor.GOLD + "Mob Action with ID #" + id + " removed!");
485 | this.plugin.saveMobsFile();
486 | return true;
487 | } else if (args[1].equalsIgnoreCase("list")) {
488 | if (args.length != 2)
489 | return false;
490 | if (mob.getInteractActions().isEmpty()) {
491 | player.sendMessage(ChatColor.GOLD + "Registered Mob Actions: " + ChatColor.WHITE + "None");
492 | } else {
493 | player.sendMessage(ChatColor.GOLD + "Registered Mob Actions:");
494 | for (int i = 0; i < mob.getInteractActions().size(); i++) {
495 | InteractAction action = mob.getInteractActions().get(i);
496 | StringBuilder builder = new StringBuilder();
497 |
498 | builder.append(ChatColor.GRAY).append("#").append(i).append(": ")
499 | .append(ChatColor.GOLD).append("Type: ").append(ChatColor.WHITE).append(action.getType().name())
500 | .append(", ")
501 | .append(ChatColor.GOLD).append("Value: ").append(ChatColor.WHITE).append(action.toString());
502 |
503 | player.sendMessage(builder.toString());
504 | }
505 | }
506 | player.sendMessage(ChatColor.GOLD + "Available Interact Actions: " + ChatColor.WHITE + InteractType.getStringList());
507 | return true;
508 | } else if (args[1].equalsIgnoreCase("clear")) {
509 | if (args.length != 2)
510 | return false;
511 | if (mob.getInteractActions().isEmpty()) {
512 | player.sendMessage(ChatColor.RED + "The Mob haven't Interact Actions!");
513 | return true;
514 | }
515 | mob.clearInteractAction();
516 | this.plugin.saveMobsFile();
517 | player.sendMessage(ChatColor.GOLD + "All Interact Actions removed!");
518 | return true;
519 | } else
520 | return false;
521 | } else if (args[0].equalsIgnoreCase("remove")) {
522 | if (args.length != 1) return false;
523 | if (!player.hasPermission("FakeMobs.remove")) {
524 | player.sendMessage(ChatColor.RED + "No permission!");
525 | return true;
526 | }
527 | FakeMob mob = Cache.selectedMobs.get(player);
528 | if (mob == null) {
529 | player.sendMessage(ChatColor.RED + "You haven't a Selection!");
530 | return true;
531 | }
532 | this.plugin.removeMob(mob.getId());
533 | player.sendMessage(ChatColor.GREEN + "Mob " + ChatColor.GRAY + "#" + mob.getId() + ChatColor.GREEN + " removed!");
534 | return true;
535 | } else if (args[0].equalsIgnoreCase("help")) {
536 | if (args.length != 1) return false;
537 | if (!player.hasPermission("FakeMobs.help")) {
538 | player.sendMessage(ChatColor.RED + "No permission!");
539 | return true;
540 | }
541 | player.sendMessage(ChatColor.GOLD + "Help for " + ChatColor.GRAY + "/FakeMob");
542 | player.sendMessage(ChatColor.GRAY + "/FakeMob create " + ChatColor.RED + "-- " + ChatColor.WHITE + "Spawn a Fakemob");
543 | player.sendMessage(ChatColor.GRAY + "/FakeMob select [id] " + ChatColor.RED + "-- " + ChatColor.WHITE + "Select a Fakemob");
544 | player.sendMessage(ChatColor.GRAY + "/FakeMob name " + ChatColor.RED + "-- " + ChatColor.WHITE + "Give the Fakemob a name");
545 | player.sendMessage(ChatColor.GRAY + "/FakeMob sitting " + ChatColor.RED + "-- " + ChatColor.WHITE + "Change the Sitting state of a pet and players (Wolf/Ocelot/Player)");
546 | player.sendMessage(ChatColor.GRAY + "/FakeMob invisibility " + ChatColor.RED + "-- " + ChatColor.WHITE + "Make the fakemob invisibility");
547 | player.sendMessage(ChatColor.GRAY + "/FakeMob look " + ChatColor.RED + "-- " + ChatColor.WHITE + "Enable/Disable the Players Look");
548 | player.sendMessage(ChatColor.GRAY + "/FakeMob teleport " + ChatColor.RED + "-- " + ChatColor.WHITE + "Teleport a Fakemob to you");
549 | player.sendMessage(ChatColor.GRAY + "/FakeMob inv " + ChatColor.RED + "-- " + ChatColor.WHITE + "Set the Inventory of a Fakemob. Use none to delete.");
550 | player.sendMessage(ChatColor.GRAY + "/FakeMob shop enable " + ChatColor.RED + "-- " + ChatColor.WHITE + "Enable the Shop");
551 | player.sendMessage(ChatColor.GRAY + "/FakeMob shop disable " + ChatColor.RED + "-- " + ChatColor.WHITE + "Disable the Shop");
552 | player.sendMessage(ChatColor.GRAY + "/FakeMob shop addItem ;[Item 2];