001    import java.util.ArrayList;
002    import java.util.List;
003    import net.minecraft.server.MinecraftServer;
004    
005    /**
006     * Server.java - Interface to server stuff
007     * 
008     * @author James
009     */
010    public class Server {
011    
012        private MinecraftServer server;
013    
014        /**
015         * Creates a server
016         * 
017         * @param server
018         */
019        public Server(MinecraftServer server) {
020            this.server = server;
021        }
022    
023        /**
024         * Sends a message to all users
025         * 
026         * @param msg
027         *            Message text to send
028         */
029        public void messageAll(String msg) {
030            this.server.f.a(new bz(msg));
031        }
032    
033        /**
034         * Bans specified player
035         *
036         * @param player Name of the player to ban
037         *
038         */
039        public void ban(String player) {
040            this.server.f.a(player);
041        }
042    
043        /**
044         * Unbans specified user
045         *
046         * @param player Player name to unban
047         *
048         */
049        public void unban(String player) {
050            this.server.f.b(player);
051        }
052    
053        /**
054         * Uses the specified console command
055         * 
056         * @param command
057         */
058        public void useConsoleCommand(String command) {
059            server.a(command, server);
060        }
061    
062        /**
063         * Uses the specified console command
064         * 
065         * @param command
066         *            command to use
067         * @param player
068         *            player to use command as
069         */
070        public void useConsoleCommand(String command, Player player) {
071            server.a(command, player.getUser().a);
072        }
073    
074        /**
075         * Starts a timer using the built-in timer system.
076         * 
077         * @param uniqueString
078         *            must be unique identifier for this timer
079         * @param time
080         *            time till it expires (6000 roughly equals 5 minutes)
081         */
082        public void setTimer(String uniqueString, int time) {
083            MinecraftServer.b.put(uniqueString, time);
084        }
085    
086        /**
087         * Check to see if your timer has expired yet.
088         * 
089         * @param uniqueString
090         *            unique identifier
091         * @return false if timer has expired
092         */
093        public boolean isTimerExpired(String uniqueString) {
094            return MinecraftServer.b.containsKey(uniqueString);
095        }
096    
097        /**
098         * Returns actual server time (-2^63 to 2^63-1)
099         * 
100         * @return time server time
101         */
102        public long getTime() {
103            return server.e.e;
104        }
105    
106        /**
107         * Returns current server time (0-24000)
108         * 
109         * @return time server time
110         */
111        public long getRelativeTime() {
112            long time = (server.e.e % 24000);
113            // Java modulus is stupid.
114            if (time < 0) {
115                time += 24000;
116            }
117            return time;
118        }
119    
120        /**
121         * Sets the actual server time
122         * 
123         * @param time
124         *            time (-2^63 to 2^63-1)
125         */
126        public void setTime(long time) {
127            server.e.e = time;
128        }
129    
130        /**
131         * Sets the current server time
132         * 
133         * @param time
134         *            time (0-24000)
135         */
136        public void setRelativeTime(long time) {
137            long margin = (time - server.e.e) % 24000;
138            // Java modulus is stupid.
139            if (margin < 0) {
140                margin += 24000;
141            }
142            server.e.e += margin;
143        }
144    
145        /**
146         * Returns the actual Minecraft Server
147         * 
148         * @return
149         */
150        public MinecraftServer getMCServer() {
151            return server;
152        }
153    
154        /**
155         * Tries to match a character's name.
156         * 
157         * @param name
158         * @return
159         */
160        public Player matchPlayer(String name) {
161            Player lastPlayer = null;
162            name = name.toLowerCase();
163    
164            for (Object player : server.f.b) {
165                String playerName = ((fy) player).aw;
166    
167                if (playerName.toLowerCase().equals(name)) {
168                    // Perfect match found
169                    lastPlayer = ((fy) player).getPlayer();
170                    break;
171                }
172                if (playerName.toLowerCase().indexOf(name.toLowerCase()) != -1) {
173                    // Partial match
174                    if (lastPlayer != null) {
175                        // Found multiple
176                        return null;
177                    }
178                    lastPlayer = ((fy) player).getPlayer();
179                }
180            }
181    
182            return lastPlayer;
183        }
184    
185        /**
186         * Returns specified player
187         * 
188         * @param name
189         * @return
190         */
191        public Player getPlayer(String name) {
192            fy user = server.f.h(name);
193            return user == null ? null : user.getPlayer();
194        }
195    
196        /**
197         * Returns the player list.
198         * @return list of players
199         */
200        public List<Player> getPlayerList() {
201            List<Player> toRet = new ArrayList<Player>();
202            for (Object o : server.f.b) {
203                toRet.add(((fy) o).getPlayer());
204            }
205            return toRet;
206        }
207    
208        /**
209         * Returns the list of mobs in all open chunks.
210         * @return list of mobs
211         */
212        public List<Mob> getMobList() {
213            List<Mob> toRet = new ArrayList<Mob>();
214            for (Object o : server.e.b) {
215                //TODO: fix.
216                if (o instanceof hq || o instanceof br) {
217                    toRet.add(new Mob((mj) o));
218                }
219            }
220            return toRet;
221        }
222    
223        /**
224         * Returns the list of animals in all open chunks.
225         * @return list of animals
226         */
227        public List<Mob> getAnimalList() {
228            List<Mob> toRet = new ArrayList<Mob>();
229            for (Object o : server.e.b) {
230                if (o instanceof bl) {
231                    toRet.add(new Mob((mj) o));
232                }
233            }
234            return toRet;
235        }
236    
237        /**
238         * Returns the list of minecarts in all open chunks.
239         * @return list of minecarts
240         */
241        public List<Minecart> getMinecartList() {
242            List<Minecart> toRet = new ArrayList<Minecart>();
243            for (Object o : server.e.b) {
244                if (o instanceof lw) {
245                    toRet.add(new Minecart((lw) o));
246                }
247            }
248            return toRet;
249        }
250    
251        /**
252         * Returns the list of boats in all open chunks.
253         * @return list of boats
254         */
255        public List<Boat> getBoatList() {
256            List<Boat> toRet = new ArrayList<Boat>();
257            for (Object o : server.e.b) {
258                if (o instanceof gu) {
259                    toRet.add(new Boat((gu) o));
260                }
261            }
262            return toRet;
263        }
264    
265        /**
266         * Returns the list of all entities in the server in open chunks.
267         * @return list of entities
268         */
269        public List<BaseEntity> getEntityList() {
270            List<BaseEntity> toRet = new ArrayList<BaseEntity>();
271            for (Object o : server.e.b) {
272                if (o instanceof hq || o instanceof br || o instanceof bl) {
273                    toRet.add(new Mob((mj) o));
274                } else if (o instanceof lw) {
275                    toRet.add(new Minecart((lw) o));
276                } else if (o instanceof gu) {
277                    toRet.add(new Boat((gu) o));
278                } else if (o instanceof fy) {
279                    toRet.add(((fy)o).getPlayer());
280                }
281            }
282            return toRet;
283        }
284    
285        /**
286         * Returns the list of all living entities (players, animals, mobs) in open chunks.
287         * @return list of living entities
288         */
289        public List<LivingEntity> getLivingEntityList() {
290            List<LivingEntity> toRet = new ArrayList<LivingEntity>();
291            for (Object o : server.e.b) {
292                if (o instanceof hq || o instanceof br || o instanceof bl) {
293                    toRet.add(new Mob((mj) o));
294                } else if (o instanceof fy) {
295                    toRet.add(((fy)o).getPlayer());
296                }
297            }
298            return toRet;
299        }
300    
301        /**
302         * Returns the list of vehicles in open chunks.
303         * @return list of vehicles
304         */
305        public List<BaseVehicle> getVehicleEntityList() {
306            List<BaseVehicle> toRet = new ArrayList<BaseVehicle>();
307            for (Object o : server.e.b) {
308                if (o instanceof lw) {
309                    toRet.add(new Minecart((lw) o));
310                } else if (o instanceof gu) {
311                    toRet.add(new Boat((gu) o));
312                }
313            }
314            return toRet;
315        }
316    
317        /**
318         * Get the global spawn location
319         * 
320         * @return Location object for spawn
321         */
322        public Location getSpawnLocation() {
323            Location spawn = new Location();
324            spawn.x = (server.e.m + 0.5D);
325            spawn.y = server.e.e(this.server.e.m, this.server.e.o) + 1.5D;
326            spawn.z = server.e.o + 0.5D;
327            spawn.rotX = 0.0F;
328            spawn.rotY = 0.0F;
329            return spawn;
330        }
331    
332        /**
333         * Sets the block
334         * 
335         * @param block
336         * @return
337         */
338        public boolean setBlock(Block block) {
339            return setBlockAt(block.getType(), block.getX(), block.getY(), block.getZ()) && setBlockData(block.getX(), block.getY(), block.getZ(), block.getData());
340        }
341    
342        /**
343         * Returns the block at the specified location
344         * 
345         * @param x
346         * @param y
347         * @param z
348         * @return block
349         */
350        public Block getBlockAt(int x, int y, int z) {
351            return new Block(getBlockIdAt(x, y, z), x, y, z, getBlockData(x, y, z));
352        }
353    
354        /**
355         * Returns the block data at the specified coordinates
356         * 
357         * @param x
358         *            x
359         * @param y
360         *            y
361         * @param z
362         *            z
363         * @return block data
364         */
365        public int getBlockData(int x, int y, int z) {
366            return server.e.b(x, y, z);
367        }
368    
369        /**
370         * Sets the block data at the specified coordinates
371         * 
372         * @param x
373         *            x
374         * @param y
375         *            y
376         * @param z
377         *            z
378         * @param data
379         *            data
380         * @return true if it was successful
381         */
382        public boolean setBlockData(int x, int y, int z, int data) {
383            boolean toRet = server.e.d(x, y, z, data);
384            etc.getMCServer().f.a(new gw(x, y, z, etc.getMCServer().e));
385            ComplexBlock block = getComplexBlock(x, y, z);
386            if (block != null) {
387                block.update();
388            }
389            return toRet;
390        }
391    
392        /**
393         * Sets the block type at the specified location
394         * 
395         * @param blockType
396         * @param x
397         * @param y
398         * @param z
399         * @return true if successful
400         */
401        public boolean setBlockAt(int blockType, int x, int y, int z) {
402            return server.e.e(x, y, z, blockType);
403        }
404    
405        /**
406         * Returns the highest block Y
407         * 
408         * @param x
409         * @param z
410         * @return highest block altitude
411         */
412        public int getHighestBlockY(int x, int z) {
413            return server.e.d(x, z);
414        }
415    
416        /**
417         * Returns the block type at the specified location
418         * 
419         * @param x
420         * @param y
421         * @param z
422         * @return block type
423         */
424        public int getBlockIdAt(int x, int y, int z) {
425            return server.e.a(x, y, z);
426        }
427    
428        /**
429         * Returns the complex block at the specified location. Null if there's no
430         * complex block there. This will also find complex-blocks spanning multiple
431         * spaces, such as double chests.
432         *
433         * @param block
434         * @return complex block
435         */
436        public ComplexBlock getComplexBlock(Block block) {
437            return getComplexBlock(block.getX(), block.getY(), block.getZ());
438        }
439    
440        /**
441         * Returns the complex block at the specified location. Null if there's no
442         * complex block there. This will also find complex-blocks spanning multiple
443         * spaces, such as double chests.
444         * 
445         * @param x
446         *            x
447         * @param y
448         *            y
449         * @param z
450         *            z
451         * @return complex block
452         */
453        public ComplexBlock getComplexBlock(int x, int y, int z) {
454            ComplexBlock result = getOnlyComplexBlock(x, y, z);
455    
456            if (result != null) {
457                if (result instanceof Chest) {
458                    Chest chest = (Chest)result;
459                    result = chest.findAttachedChest();
460    
461                    if (result != null) {
462                        return result;
463                    } else {
464                        return chest;
465                    }
466                }
467            }
468    
469            return result;
470        }
471    
472        /**
473         * Returns the only complex block at the specified location. Null if there's
474         * no complex block there.
475         *
476         * @param block
477         * @return complex block
478         */
479        public ComplexBlock getOnlyComplexBlock(Block block) {
480            return getOnlyComplexBlock(block.getX(), block.getY(), block.getZ());
481        }
482    
483        /**
484         * Returns the complex block at the specified location. Null if there's no
485         * complex block there.
486         *
487         * @param x
488         *            x
489         * @param y
490         *            y
491         * @param z
492         *            z
493         * @return complex block
494         */
495        public ComplexBlock getOnlyComplexBlock(int x, int y, int z) {
496            bm localav = server.e.m(x, y, z);
497            if (localav != null) {
498                if (localav instanceof kc) {
499                    return new Chest((kc) localav);
500                } else if (localav instanceof lv) {
501                    return new Sign((lv) localav);
502                } else if (localav instanceof ez) {
503                    return new Furnace((ez) localav);
504                } else if (localav instanceof db) {
505                    return new MobSpawner((db) localav);
506                }
507            }
508            return null;
509        }
510    
511        /**
512         * Drops an item at the specified location
513         * @param loc
514         * @param itemId
515         */
516        public void dropItem(Location loc, int itemId) {
517            dropItem(loc.x, loc.y, loc.z, itemId, 1);
518        }
519    
520        /**
521         * Drops an item at the specified location
522         * @param x
523         * @param y
524         * @param z
525         * @param itemId
526         */
527        public void dropItem(double x, double y, double z, int itemId) {
528            dropItem(x, y, z, itemId, 1);
529        }
530    
531        /**
532         * Drops an item with desired quantity at the specified location
533         * @param loc
534         * @param itemId
535         * @param quantity
536         */
537        public void dropItem(Location loc, int itemId, int quantity) {
538            dropItem(loc.x, loc.y, loc.z, itemId, quantity);
539        }
540    
541        /**
542         * Drops an item with desired quantity at the specified location
543         * @param x
544         * @param y
545         * @param z
546         * @param itemId
547         * @param quantity
548         */
549        public void dropItem(double x, double y, double z, int itemId, int quantity) {
550            double d1 = server.e.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
551            double d2 = server.e.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
552            double d3 = server.e.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
553    
554            ic localgl = new ic(server.e, x + d1, y + d2, z + d3, new jl(itemId, quantity,0));
555            localgl.c = 10;
556            server.e.a(localgl);
557        }
558    
559        /**
560         * Forces the server to update the physics for blocks around the given block
561         * @param block the block that changed
562         */
563        public void updateBlockPhysics(Block block) {
564            updateBlockPhysics(block.getX(), block.getY(), block.getZ(), block.getData());
565        }
566    
567        /**
568         * Forces the server to update the physics for blocks around the given block
569         * @param x the X coordinate of the block
570         * @param y the Y coordinate of the block
571         * @param z the Z coordinate of the block
572         * @param data the new data for the block
573         */
574        public void updateBlockPhysics(int x, int y, int z, int data) {
575            server.e.c(x, y, z, data);
576        }
577    
578        /**
579         * Adds a runnable to the Server Queue, so that it will be executed in the Server Thread.
580         *  
581         * @param r - the runnable
582         */
583        public void addToServerQueue(Runnable r) {
584            addToServerQueue(r, 0L);
585        }
586    
587        /**
588         * Executes a runnable in the server thread after a specified delay.
589         *  
590         * @param r           - the runnable
591         * @param delayMillis - the delay in milliseconds
592         */
593        public void addToServerQueue(Runnable r, long delayMillis) {
594            im.add(r, delayMillis);
595        }
596        
597        /**
598         * Saves all player inventories to file
599         */
600        public void saveInventories() {
601            server.f.d();
602        }
603    
604        /**
605         * Checks to see whether or not the chunk containing the given block is
606         * loaded into memory.
607         * 
608         * @param block the Block to check
609         * @return true if the chunk is loaded
610         */
611        public boolean isChunkLoaded(Block block) {
612            return isChunkLoaded(block.getX(), block.getY(), block.getZ());
613        }
614    
615        /**
616         * Checks to see whether or not the chunk containing the given block
617         * coordinates is loaded into memory.
618         * 
619         * @param x a block x-coordinate
620         * @param y a block y-coordinate
621         * @param z a block z-coordinate
622         * @return true if the chunk is loaded
623         */
624        public boolean isChunkLoaded(int x, int y, int z) {
625            return this.server.e.A.a(x >> 4, z >> 4);
626        }
627    
628        /**
629         * Loads the chunk containing the given block. If the chunk does not
630         * exist, it will be generated.
631         *
632         * @param block the Block to check
633         */
634        public void loadChunk(Block block) {
635            loadChunk(block.getX(), block.getY(), block.getZ());
636        }
637    
638        /**
639         * Loads the chunk containing the given block coordinates. If the chunk
640         * does not exist, it will be generated.
641         *
642         * @param x a block x-coordinate
643         * @param y a block y-coordinate
644         * @param z a block z-coordinate
645         */
646        public void loadChunk(int x, int y, int z) {
647            loadChunk(x >> 4, z >> 4);
648        }
649    
650        /**
651         * Loads the chunk containing the given chunk coordinates. If the chunk
652         * does not exist, it will be generated.
653         *
654         * @param x a chunk x-coordinate
655         * @param z a chunk z-coordinate
656         */
657        public void loadChunk(int x, int z) {
658            this.server.e.A.d(x, z);
659        }
660    
661        /**
662         * Checks if the provided block is being powered through redstone
663         * 
664         * @param block Block to check
665         * @return true if the block is being powered
666         */
667        public boolean isBlockPowered(Block block) {
668            return isBlockPowered(block.getX(), block.getY(), block.getZ());
669        }
670    
671        /**
672         * Checks if the provided block is being powered through redstone
673         *
674         * @param x a block x-coordinate
675         * @param y a block y-coordinate
676         * @param z a block z-coordinate
677         * @return true if the block is being powered
678         */
679        public boolean isBlockPowered(int x, int y, int z) {
680            return this.server.e.o(x, y, z);
681        }
682    
683        /**
684         * Checks if the provided block is being indirectly powered through redstone
685         *
686         * @param block Block to check
687         * @return true if the block is being indirectly powered
688         */
689        public boolean isBlockIndirectlyPowered(Block block) {
690            return isBlockIndirectlyPowered(block.getX(), block.getY(), block.getZ());
691        }
692    
693        /**
694         * Checks if the provided block is being indirectly powered through redstone
695         *
696         * @param x a block x-coordinate
697         * @param y a block y-coordinate
698         * @param z a block z-coordinate
699         * @return true if the block is being indirectly powered
700         */
701        public boolean isBlockIndirectlyPowered(int x, int y, int z) {
702            return this.server.e.o(x, y, z);
703        }
704    }