Commits

Wesley Wolfe authored b602b5efa44
Implement new getOnlinePlayers.

Adds BUKKIt-5668
No tags

src/main/java/org/bukkit/craftbukkit/CraftServer.java

Modified
116 116 import org.bukkit.command.CommandException;
117 117 import org.bukkit.command.CommandSender;
118 118 import org.bukkit.command.ConsoleCommandSender;
119 119 import org.bukkit.command.PluginCommand;
120 120 import org.bukkit.command.SimpleCommandMap;
121 121 import org.bukkit.configuration.ConfigurationSection;
122 122 import org.bukkit.configuration.file.YamlConfiguration;
123 123 import org.bukkit.configuration.serialization.ConfigurationSerialization;
124 124 import org.bukkit.conversations.Conversable;
125 125 import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
126 +import org.bukkit.craftbukkit.entity.CraftPlayer;
126 127 import org.bukkit.craftbukkit.help.SimpleHelpMap;
127 128 import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
128 129 import org.bukkit.craftbukkit.inventory.CraftInventoryCustom;
129 130 import org.bukkit.craftbukkit.inventory.CraftItemFactory;
130 131 import org.bukkit.craftbukkit.inventory.CraftRecipe;
131 132 import org.bukkit.craftbukkit.inventory.CraftShapedRecipe;
132 133 import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe;
133 134 import org.bukkit.craftbukkit.inventory.RecipeIterator;
134 135 import org.bukkit.craftbukkit.map.CraftMapView;
135 136 import org.bukkit.craftbukkit.metadata.EntityMetadataStore;
178 179 import org.bukkit.util.permissions.DefaultPermissions;
179 180 import org.yaml.snakeyaml.Yaml;
180 181 import org.yaml.snakeyaml.constructor.SafeConstructor;
181 182 import org.yaml.snakeyaml.error.MarkedYAMLException;
182 183 import org.apache.commons.lang.Validate;
183 184
184 185 import com.avaje.ebean.config.DataSourceConfig;
185 186 import com.avaje.ebean.config.ServerConfig;
186 187 import com.avaje.ebean.config.dbplatform.SQLitePlatform;
187 188 import com.avaje.ebeaninternal.server.lib.sql.TransactionIsolation;
189 +import com.google.common.base.Function;
188 190 import com.google.common.collect.ImmutableList;
191 +import com.google.common.collect.Lists;
189 192 import com.google.common.collect.MapMaker;
190 193
191 194 import jline.console.ConsoleReader;
192 195
193 196 public final class CraftServer implements Server {
197 + private static final Player[] EMPTY_PLAYER_ARRAY = new Player[0];
194 198 private final String serverName = "CraftBukkit";
195 199 private final String serverVersion;
196 200 private final String bukkitVersion = Versioning.getBukkitVersion();
197 201 private final Logger logger = Logger.getLogger("Minecraft");
198 202 private final ServicesManager servicesManager = new SimpleServicesManager();
199 203 private final CraftScheduler scheduler = new CraftScheduler();
200 204 private final SimpleCommandMap commandMap = new SimpleCommandMap(this);
201 205 private final SimpleHelpMap helpMap = new SimpleHelpMap(this);
202 206 private final StandardMessenger messenger = new StandardMessenger();
203 207 private final PluginManager pluginManager = new SimplePluginManager(this, commandMap);
221 225 private File container;
222 226 private WarningState warningState = WarningState.DEFAULT;
223 227 private final BooleanWrapper online = new BooleanWrapper();
224 228 public CraftScoreboardManager scoreboardManager;
225 229 public boolean playerCommandState;
226 230 private boolean printSaveWarning;
227 231 private CraftIconCache icon;
228 232 private boolean overrideAllCommandBlockCommands = false;
229 233 private final Pattern validUserPattern = Pattern.compile("^[a-zA-Z0-9_]{2,16}$");
230 234 private final UUID invalidUserUUID = UUID.nameUUIDFromBytes("InvalidUsername".getBytes(Charsets.UTF_8));
235 + private final List<CraftPlayer> playerView;
231 236
232 237 private final class BooleanWrapper {
233 238 private boolean value = true;
234 239 }
235 240
236 241 static {
237 242 ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
238 243 CraftItemFactory.instance();
239 244 }
240 245
241 246 public CraftServer(MinecraftServer console, PlayerList playerList) {
242 247 this.console = console;
243 248 this.playerList = (DedicatedPlayerList) playerList;
249 + this.playerView = Collections.unmodifiableList(Lists.transform(playerList.players, new Function<EntityPlayer, CraftPlayer>() {
250 + @Override
251 + public CraftPlayer apply(EntityPlayer player) {
252 + return player.getBukkitEntity();
253 + }
254 + }));
244 255 this.serverVersion = CraftServer.class.getPackage().getImplementationVersion();
245 256 online.value = console.getPropertyManager().getBoolean("online-mode", true);
246 257
247 258 Bukkit.setServer(this);
248 259
249 260 // Register all the Enchantments and PotionTypes now so we can stop new registration immediately after
250 261 Enchantment.DAMAGE_ALL.getClass();
251 262 org.bukkit.enchantments.Enchantment.stopAcceptingRegistrations();
252 263
253 264 Potion.setPotionBrewer(new CraftPotionBrewer());
452 463 pluginManager.addPermission(perm);
453 464 } catch (IllegalArgumentException ex) {
454 465 getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex);
455 466 }
456 467 }
457 468 } catch (Throwable ex) {
458 469 Logger.getLogger(CraftServer.class.getName()).log(Level.SEVERE, ex.getMessage() + " loading " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
459 470 }
460 471 }
461 472
473 + @Override
462 474 public String getName() {
463 475 return serverName;
464 476 }
465 477
478 + @Override
466 479 public String getVersion() {
467 480 return serverVersion + " (MC: " + console.getVersion() + ")";
468 481 }
469 482
483 + @Override
470 484 public String getBukkitVersion() {
471 485 return bukkitVersion;
472 486 }
473 487
488 + @Override
489 + @Deprecated
474 490 @SuppressWarnings("unchecked")
475 - public Player[] getOnlinePlayers() {
476 - List<EntityPlayer> online = playerList.players;
477 - Player[] players = new Player[online.size()];
478 -
479 - for (int i = 0; i < players.length; i++) {
480 - players[i] = online.get(i).playerConnection.getPlayer();
481 - }
491 + public Player[] _INVALID_getOnlinePlayers() {
492 + return getOnlinePlayers().toArray(EMPTY_PLAYER_ARRAY);
493 + }
482 494
483 - return players;
495 + @Override
496 + public List<CraftPlayer> getOnlinePlayers() {
497 + return this.playerView;
484 498 }
485 499
500 + @Override
501 + @Deprecated
486 502 public Player getPlayer(final String name) {
487 503 Validate.notNull(name, "Name cannot be null");
488 504
489 - Player[] players = getOnlinePlayers();
490 -
491 505 Player found = null;
492 506 String lowerName = name.toLowerCase();
493 507 int delta = Integer.MAX_VALUE;
494 - for (Player player : players) {
508 + for (Player player : getOnlinePlayers()) {
495 509 if (player.getName().toLowerCase().startsWith(lowerName)) {
496 510 int curDelta = player.getName().length() - lowerName.length();
497 511 if (curDelta < delta) {
498 512 found = player;
499 513 delta = curDelta;
500 514 }
501 515 if (curDelta == 0) break;
502 516 }
503 517 }
504 518 return found;
505 519 }
506 520
521 + @Override
522 + @Deprecated
507 523 public Player getPlayerExact(String name) {
508 524 Validate.notNull(name, "Name cannot be null");
509 525
510 526 String lname = name.toLowerCase();
511 527
512 528 for (Player player : getOnlinePlayers()) {
513 529 if (player.getName().equalsIgnoreCase(lname)) {
514 530 return player;
515 531 }
516 532 }
517 533
518 534 return null;
519 535 }
520 536
521 537 // TODO: In 1.8+ this should use the server's UUID->EntityPlayer map
538 + @Override
522 539 public Player getPlayer(UUID id) {
523 540 for (Player player : getOnlinePlayers()) {
524 541 if (player.getUniqueId().equals(id)) {
525 542 return player;
526 543 }
527 544 }
528 545
529 546 return null;
530 547 }
531 548
549 + @Override
532 550 public int broadcastMessage(String message) {
533 551 return broadcast(message, BROADCAST_CHANNEL_USERS);
534 552 }
535 553
536 554 public Player getPlayer(final EntityPlayer entity) {
537 555 return entity.playerConnection.getPlayer();
538 556 }
539 557
558 + @Override
559 + @Deprecated
540 560 public List<Player> matchPlayer(String partialName) {
541 561 Validate.notNull(partialName, "PartialName cannot be null");
542 562
543 563 List<Player> matchedPlayers = new ArrayList<Player>();
544 564
545 565 for (Player iterPlayer : this.getOnlinePlayers()) {
546 566 String iterPlayerName = iterPlayer.getName();
547 567
548 568 if (partialName.equalsIgnoreCase(iterPlayerName)) {
549 569 // Exact match
553 573 }
554 574 if (iterPlayerName.toLowerCase().contains(partialName.toLowerCase())) {
555 575 // Partial match
556 576 matchedPlayers.add(iterPlayer);
557 577 }
558 578 }
559 579
560 580 return matchedPlayers;
561 581 }
562 582
583 + @Override
563 584 public int getMaxPlayers() {
564 585 return playerList.getMaxPlayers();
565 586 }
566 587
567 588 // NOTE: These are dependent on the corrisponding call in MinecraftServer
568 589 // so if that changes this will need to as well
590 + @Override
569 591 public int getPort() {
570 592 return this.getConfigInt("server-port", 25565);
571 593 }
572 594
595 + @Override
573 596 public int getViewDistance() {
574 597 return this.getConfigInt("view-distance", 10);
575 598 }
576 599
600 + @Override
577 601 public String getIp() {
578 602 return this.getConfigString("server-ip", "");
579 603 }
580 604
605 + @Override
581 606 public String getServerName() {
582 607 return this.getConfigString("server-name", "Unknown Server");
583 608 }
584 609
610 + @Override
585 611 public String getServerId() {
586 612 return this.getConfigString("server-id", "unnamed");
587 613 }
588 614
615 + @Override
589 616 public String getWorldType() {
590 617 return this.getConfigString("level-type", "DEFAULT");
591 618 }
592 619
620 + @Override
593 621 public boolean getGenerateStructures() {
594 622 return this.getConfigBoolean("generate-structures", true);
595 623 }
596 624
625 + @Override
597 626 public boolean getAllowEnd() {
598 627 return this.configuration.getBoolean("settings.allow-end");
599 628 }
600 629
630 + @Override
601 631 public boolean getAllowNether() {
602 632 return this.getConfigBoolean("allow-nether", true);
603 633 }
604 634
605 635 public boolean getWarnOnOverload() {
606 636 return this.configuration.getBoolean("settings.warn-on-overload");
607 637 }
608 638
609 639 public boolean getQueryPlugins() {
610 640 return this.configuration.getBoolean("settings.query-plugins");
611 641 }
612 642
643 + @Override
613 644 public boolean hasWhitelist() {
614 645 return this.getConfigBoolean("white-list", false);
615 646 }
616 647
617 648 // NOTE: Temporary calls through to server.properies until its replaced
618 649 private String getConfigString(String variable, String defaultValue) {
619 650 return this.console.getPropertyManager().getString(variable, defaultValue);
620 651 }
621 652
622 653 private int getConfigInt(String variable, int defaultValue) {
623 654 return this.console.getPropertyManager().getInt(variable, defaultValue);
624 655 }
625 656
626 657 private boolean getConfigBoolean(String variable, boolean defaultValue) {
627 658 return this.console.getPropertyManager().getBoolean(variable, defaultValue);
628 659 }
629 660
630 661 // End Temporary calls
631 662
663 + @Override
632 664 public String getUpdateFolder() {
633 665 return this.configuration.getString("settings.update-folder", "update");
634 666 }
635 667
668 + @Override
636 669 public File getUpdateFolderFile() {
637 670 return new File((File) console.options.valueOf("plugins"), this.configuration.getString("settings.update-folder", "update"));
638 671 }
639 672
640 673 public int getPingPacketLimit() {
641 674 return this.configuration.getInt("settings.ping-packet-limit", 100);
642 675 }
643 676
677 + @Override
644 678 public long getConnectionThrottle() {
645 679 return this.configuration.getInt("settings.connection-throttle");
646 680 }
647 681
682 + @Override
648 683 public int getTicksPerAnimalSpawns() {
649 684 return this.configuration.getInt("ticks-per.animal-spawns");
650 685 }
651 686
687 + @Override
652 688 public int getTicksPerMonsterSpawns() {
653 689 return this.configuration.getInt("ticks-per.monster-spawns");
654 690 }
655 691
692 + @Override
656 693 public PluginManager getPluginManager() {
657 694 return pluginManager;
658 695 }
659 696
697 + @Override
660 698 public CraftScheduler getScheduler() {
661 699 return scheduler;
662 700 }
663 701
702 + @Override
664 703 public ServicesManager getServicesManager() {
665 704 return servicesManager;
666 705 }
667 706
707 + @Override
668 708 public List<World> getWorlds() {
669 709 return new ArrayList<World>(worlds.values());
670 710 }
671 711
672 712 public DedicatedPlayerList getHandle() {
673 713 return playerList;
674 714 }
675 715
676 716 // NOTE: Should only be called from DedicatedServer.ah()
677 717 public boolean dispatchServerCommand(CommandSender sender, ServerCommand serverCommand) {
687 727 this.playerCommandState = true;
688 728 return dispatchCommand(sender, serverCommand.command);
689 729 } catch (Exception ex) {
690 730 getLogger().log(Level.WARNING, "Unexpected exception while parsing console command \"" + serverCommand.command + '"', ex);
691 731 return false;
692 732 } finally {
693 733 this.playerCommandState = false;
694 734 }
695 735 }
696 736
737 + @Override
697 738 public boolean dispatchCommand(CommandSender sender, String commandLine) {
698 739 Validate.notNull(sender, "Sender cannot be null");
699 740 Validate.notNull(commandLine, "CommandLine cannot be null");
700 741
701 742 if (commandMap.dispatch(sender, commandLine)) {
702 743 return true;
703 744 }
704 745
705 746 if (sender instanceof Player) {
706 747 sender.sendMessage("Unknown command. Type \"/help\" for help.");
707 748 } else {
708 749 sender.sendMessage("Unknown command. Type \"help\" for help.");
709 750 }
710 751
711 752 return false;
712 753 }
713 754
755 + @Override
714 756 public void reload() {
715 757 configuration = YamlConfiguration.loadConfiguration(getConfigFile());
716 758 commandsConfiguration = YamlConfiguration.loadConfiguration(getCommandsConfigFile());
717 759 PropertyManager config = new PropertyManager(console.options);
718 760
719 761 ((DedicatedServer) console).propertyManager = config;
720 762
721 763 boolean animals = config.getBoolean("spawn-animals", console.getSpawnAnimals());
722 764 boolean monsters = config.getBoolean("spawn-monsters", console.worlds.get(0).difficulty != EnumDifficulty.PEACEFUL);
723 765 EnumDifficulty difficulty = EnumDifficulty.a(config.getInt("difficulty", console.worlds.get(0).difficulty.ordinal()));
872 914 }
873 915
874 916 public World createWorld(String name, Environment environment, ChunkGenerator generator) {
875 917 return WorldCreator.name(name).environment(environment).generator(generator).createWorld();
876 918 }
877 919
878 920 public World createWorld(String name, Environment environment, long seed, ChunkGenerator generator) {
879 921 return WorldCreator.name(name).environment(environment).seed(seed).generator(generator).createWorld();
880 922 }
881 923
924 + @Override
882 925 public World createWorld(WorldCreator creator) {
883 926 Validate.notNull(creator, "Creator may not be null");
884 927
885 928 String name = creator.name();
886 929 ChunkGenerator generator = creator.generator();
887 930 File folder = new File(getWorldContainer(), name);
888 931 World world = getWorld(name);
889 932 WorldType type = WorldType.getType(creator.type().getName());
890 933 boolean generateStructures = creator.generateStructures();
891 934
962 1005
963 1006 ChunkCoordinates chunkcoordinates = internal.getSpawn();
964 1007 internal.chunkProviderServer.getChunkAt(chunkcoordinates.x + j >> 4, chunkcoordinates.z + k >> 4);
965 1008 }
966 1009 }
967 1010 }
968 1011 pluginManager.callEvent(new WorldLoadEvent(internal.getWorld()));
969 1012 return internal.getWorld();
970 1013 }
971 1014
1015 + @Override
972 1016 public boolean unloadWorld(String name, boolean save) {
973 1017 return unloadWorld(getWorld(name), save);
974 1018 }
975 1019
1020 + @Override
976 1021 public boolean unloadWorld(World world, boolean save) {
977 1022 if (world == null) {
978 1023 return false;
979 1024 }
980 1025
981 1026 WorldServer handle = ((CraftWorld) world).getHandle();
982 1027
983 1028 if (!(console.worlds.contains(handle))) {
984 1029 return false;
985 1030 }
1013 1058 worlds.remove(world.getName().toLowerCase());
1014 1059 console.worlds.remove(console.worlds.indexOf(handle));
1015 1060
1016 1061 return true;
1017 1062 }
1018 1063
1019 1064 public MinecraftServer getServer() {
1020 1065 return console;
1021 1066 }
1022 1067
1068 + @Override
1023 1069 public World getWorld(String name) {
1024 1070 Validate.notNull(name, "Name cannot be null");
1025 1071
1026 1072 return worlds.get(name.toLowerCase());
1027 1073 }
1028 1074
1075 + @Override
1029 1076 public World getWorld(UUID uid) {
1030 1077 for (World world : worlds.values()) {
1031 1078 if (world.getUID().equals(uid)) {
1032 1079 return world;
1033 1080 }
1034 1081 }
1035 1082 return null;
1036 1083 }
1037 1084
1038 1085 public void addWorld(World world) {
1039 1086 // Check if a World already exists with the UID.
1040 1087 if (getWorld(world.getUID()) != null) {
1041 1088 System.out.println("World " + world.getName() + " is a duplicate of another world and has been prevented from loading. Please delete the uid.dat file from " + world.getName() + "'s world directory if you want to be able to load the duplicate world.");
1042 1089 return;
1043 1090 }
1044 1091 worlds.put(world.getName().toLowerCase(), world);
1045 1092 }
1046 1093
1094 + @Override
1047 1095 public Logger getLogger() {
1048 1096 return logger;
1049 1097 }
1050 1098
1051 1099 public ConsoleReader getReader() {
1052 1100 return console.reader;
1053 1101 }
1054 1102
1103 + @Override
1055 1104 public PluginCommand getPluginCommand(String name) {
1056 1105 Command command = commandMap.getCommand(name);
1057 1106
1058 1107 if (command instanceof PluginCommand) {
1059 1108 return (PluginCommand) command;
1060 1109 } else {
1061 1110 return null;
1062 1111 }
1063 1112 }
1064 1113
1114 + @Override
1065 1115 public void savePlayers() {
1066 1116 checkSaveState();
1067 1117 playerList.savePlayers();
1068 1118 }
1069 1119
1120 + @Override
1070 1121 public void configureDbConfig(ServerConfig config) {
1071 1122 Validate.notNull(config, "Config cannot be null");
1072 1123
1073 1124 DataSourceConfig ds = new DataSourceConfig();
1074 1125 ds.setDriver(configuration.getString("database.driver"));
1075 1126 ds.setUrl(configuration.getString("database.url"));
1076 1127 ds.setUsername(configuration.getString("database.username"));
1077 1128 ds.setPassword(configuration.getString("database.password"));
1078 1129 ds.setIsolationLevel(TransactionIsolation.getLevel(configuration.getString("database.isolation")));
1079 1130
1080 1131 if (ds.getDriver().contains("sqlite")) {
1081 1132 config.setDatabasePlatform(new SQLitePlatform());
1082 1133 config.getDatabasePlatform().getDbDdlSyntax().setIdentity("");
1083 1134 }
1084 1135
1085 1136 config.setDataSourceConfig(ds);
1086 1137 }
1087 1138
1139 + @Override
1088 1140 public boolean addRecipe(Recipe recipe) {
1089 1141 CraftRecipe toAdd;
1090 1142 if (recipe instanceof CraftRecipe) {
1091 1143 toAdd = (CraftRecipe) recipe;
1092 1144 } else {
1093 1145 if (recipe instanceof ShapedRecipe) {
1094 1146 toAdd = CraftShapedRecipe.fromBukkitRecipe((ShapedRecipe) recipe);
1095 1147 } else if (recipe instanceof ShapelessRecipe) {
1096 1148 toAdd = CraftShapelessRecipe.fromBukkitRecipe((ShapelessRecipe) recipe);
1097 1149 } else if (recipe instanceof FurnaceRecipe) {
1098 1150 toAdd = CraftFurnaceRecipe.fromBukkitRecipe((FurnaceRecipe) recipe);
1099 1151 } else {
1100 1152 return false;
1101 1153 }
1102 1154 }
1103 1155 toAdd.addToCraftingManager();
1104 1156 CraftingManager.getInstance().sort();
1105 1157 return true;
1106 1158 }
1107 1159
1160 + @Override
1108 1161 public List<Recipe> getRecipesFor(ItemStack result) {
1109 1162 Validate.notNull(result, "Result cannot be null");
1110 1163
1111 1164 List<Recipe> results = new ArrayList<Recipe>();
1112 1165 Iterator<Recipe> iter = recipeIterator();
1113 1166 while (iter.hasNext()) {
1114 1167 Recipe recipe = iter.next();
1115 1168 ItemStack stack = recipe.getResult();
1116 1169 if (stack.getType() != result.getType()) {
1117 1170 continue;
1118 1171 }
1119 1172 if (result.getDurability() == -1 || result.getDurability() == stack.getDurability()) {
1120 1173 results.add(recipe);
1121 1174 }
1122 1175 }
1123 1176 return results;
1124 1177 }
1125 1178
1179 + @Override
1126 1180 public Iterator<Recipe> recipeIterator() {
1127 1181 return new RecipeIterator();
1128 1182 }
1129 1183
1184 + @Override
1130 1185 public void clearRecipes() {
1131 1186 CraftingManager.getInstance().recipes.clear();
1132 1187 RecipesFurnace.getInstance().recipes.clear();
1133 1188 RecipesFurnace.getInstance().customRecipes.clear();
1134 1189 }
1135 1190
1191 + @Override
1136 1192 public void resetRecipes() {
1137 1193 CraftingManager.getInstance().recipes = new CraftingManager().recipes;
1138 1194 RecipesFurnace.getInstance().recipes = new RecipesFurnace().recipes;
1139 1195 RecipesFurnace.getInstance().customRecipes.clear();
1140 1196 }
1141 1197
1198 + @Override
1142 1199 public Map<String, String[]> getCommandAliases() {
1143 1200 ConfigurationSection section = commandsConfiguration.getConfigurationSection("aliases");
1144 1201 Map<String, String[]> result = new LinkedHashMap<String, String[]>();
1145 1202
1146 1203 if (section != null) {
1147 1204 for (String key : section.getKeys(false)) {
1148 1205 List<String> commands;
1149 1206
1150 1207 if (section.isList(key)) {
1151 1208 commands = section.getStringList(key);
1162 1219
1163 1220 public void removeBukkitSpawnRadius() {
1164 1221 configuration.set("settings.spawn-radius", null);
1165 1222 saveConfig();
1166 1223 }
1167 1224
1168 1225 public int getBukkitSpawnRadius() {
1169 1226 return configuration.getInt("settings.spawn-radius", -1);
1170 1227 }
1171 1228
1229 + @Override
1172 1230 public String getShutdownMessage() {
1173 1231 return configuration.getString("settings.shutdown-message");
1174 1232 }
1175 1233
1234 + @Override
1176 1235 public int getSpawnRadius() {
1177 1236 return ((DedicatedServer) console).propertyManager.getInt("spawn-protection", 16);
1178 1237 }
1179 1238
1239 + @Override
1180 1240 public void setSpawnRadius(int value) {
1181 1241 configuration.set("settings.spawn-radius", value);
1182 1242 saveConfig();
1183 1243 }
1184 1244
1245 + @Override
1185 1246 public boolean getOnlineMode() {
1186 1247 return online.value;
1187 1248 }
1188 1249
1250 + @Override
1189 1251 public boolean getAllowFlight() {
1190 1252 return console.getAllowFlight();
1191 1253 }
1192 1254
1255 + @Override
1193 1256 public boolean isHardcore() {
1194 1257 return console.isHardcore();
1195 1258 }
1196 1259
1260 + @Override
1197 1261 public boolean useExactLoginLocation() {
1198 1262 return configuration.getBoolean("settings.use-exact-login-location");
1199 1263 }
1200 1264
1201 1265 public ChunkGenerator getGenerator(String world) {
1202 1266 ConfigurationSection section = configuration.getConfigurationSection("worlds");
1203 1267 ChunkGenerator result = null;
1204 1268
1205 1269 if (section != null) {
1206 1270 section = section.getConfigurationSection(world);
1227 1291 plugin.getLogger().log(Level.SEVERE, "Could not set generator for default world '" + world + "': Plugin '" + plugin.getDescription().getFullName(), t);
1228 1292 }
1229 1293 }
1230 1294 }
1231 1295 }
1232 1296 }
1233 1297
1234 1298 return result;
1235 1299 }
1236 1300
1301 + @Override
1302 + @Deprecated
1237 1303 public CraftMapView getMap(short id) {
1238 1304 PersistentCollection collection = console.worlds.get(0).worldMaps;
1239 1305 WorldMap worldmap = (WorldMap) collection.get(WorldMap.class, "map_" + id);
1240 1306 if (worldmap == null) {
1241 1307 return null;
1242 1308 }
1243 1309 return worldmap.mapView;
1244 1310 }
1245 1311
1312 + @Override
1246 1313 public CraftMapView createMap(World world) {
1247 1314 Validate.notNull(world, "World cannot be null");
1248 1315
1249 1316 net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(Items.MAP, 1, -1);
1250 1317 WorldMap worldmap = Items.MAP.getSavedMap(stack, ((CraftWorld) world).getHandle());
1251 1318 return worldmap.mapView;
1252 1319 }
1253 1320
1321 + @Override
1254 1322 public void shutdown() {
1255 1323 console.safeShutdown();
1256 1324 }
1257 1325
1326 + @Override
1258 1327 public int broadcast(String message, String permission) {
1259 1328 int count = 0;
1260 1329 Set<Permissible> permissibles = getPluginManager().getPermissionSubscriptions(permission);
1261 1330
1262 1331 for (Permissible permissible : permissibles) {
1263 1332 if (permissible instanceof CommandSender && permissible.hasPermission(permission)) {
1264 1333 CommandSender user = (CommandSender) permissible;
1265 1334 user.sendMessage(message);
1266 1335 count++;
1267 1336 }
1268 1337 }
1269 1338
1270 1339 return count;
1271 1340 }
1272 1341
1342 + @Override
1343 + @Deprecated
1273 1344 public OfflinePlayer getOfflinePlayer(String name) {
1274 1345 Validate.notNull(name, "Name cannot be null");
1275 1346
1276 1347 // If the name given cannot ever be a valid username give a dummy return, for scoreboard plugins
1277 1348 if (!validUserPattern.matcher(name).matches()) {
1278 1349 return new CraftOfflinePlayer(this, new GameProfile(invalidUserUUID, name));
1279 1350 }
1280 1351
1281 1352 OfflinePlayer result = getPlayerExact(name);
1282 1353 if (result == null) {
1289 1360 // Use the GameProfile even when we get a UUID so we ensure we still have a name
1290 1361 result = getOfflinePlayer(profile);
1291 1362 }
1292 1363 } else {
1293 1364 offlinePlayers.remove(result.getUniqueId());
1294 1365 }
1295 1366
1296 1367 return result;
1297 1368 }
1298 1369
1370 + @Override
1299 1371 public OfflinePlayer getOfflinePlayer(UUID id) {
1300 1372 Validate.notNull(id, "UUID cannot be null");
1301 1373
1302 1374 OfflinePlayer result = getPlayer(id);
1303 1375 if (result == null) {
1304 1376 result = offlinePlayers.get(id);
1305 1377 if (result == null) {
1306 1378 result = new CraftOfflinePlayer(this, new GameProfile(id, null));
1307 1379 offlinePlayers.put(id, result);
1308 1380 }
1312 1384
1313 1385 return result;
1314 1386 }
1315 1387
1316 1388 public OfflinePlayer getOfflinePlayer(GameProfile profile) {
1317 1389 OfflinePlayer player = new CraftOfflinePlayer(this, profile);
1318 1390 offlinePlayers.put(profile.getId(), player);
1319 1391 return player;
1320 1392 }
1321 1393
1394 + @Override
1322 1395 @SuppressWarnings("unchecked")
1323 1396 public Set<String> getIPBans() {
1324 1397 return new HashSet<String>(Arrays.asList(playerList.getIPBans().getEntries()));
1325 1398 }
1326 1399
1400 + @Override
1327 1401 public void banIP(String address) {
1328 1402 Validate.notNull(address, "Address cannot be null.");
1329 1403
1330 1404 this.getBanList(org.bukkit.BanList.Type.IP).addBan(address, null, null, null);
1331 1405 }
1332 1406
1407 + @Override
1333 1408 public void unbanIP(String address) {
1334 1409 Validate.notNull(address, "Address cannot be null.");
1335 1410
1336 1411 this.getBanList(org.bukkit.BanList.Type.IP).pardon(address);
1337 1412 }
1338 1413
1414 + @Override
1339 1415 public Set<OfflinePlayer> getBannedPlayers() {
1340 1416 Set<OfflinePlayer> result = new HashSet<OfflinePlayer>();
1341 1417
1342 1418 for (JsonListEntry entry : playerList.getProfileBans().getValues()) {
1343 1419 result.add(getOfflinePlayer((GameProfile) entry.f())); // Should be getKey
1344 1420 }
1345 1421
1346 1422 return result;
1347 1423 }
1348 1424
1352 1428
1353 1429 switch(type){
1354 1430 case IP:
1355 1431 return new CraftIpBanList(playerList.getIPBans());
1356 1432 case NAME:
1357 1433 default:
1358 1434 return new CraftProfileBanList(playerList.getProfileBans());
1359 1435 }
1360 1436 }
1361 1437
1438 + @Override
1362 1439 public void setWhitelist(boolean value) {
1363 1440 playerList.setHasWhitelist(value);
1364 1441 console.getPropertyManager().a("white-list", value);
1365 1442 }
1366 1443
1444 + @Override
1367 1445 public Set<OfflinePlayer> getWhitelistedPlayers() {
1368 1446 Set<OfflinePlayer> result = new LinkedHashSet<OfflinePlayer>();
1369 1447
1370 1448 for (JsonListEntry entry : playerList.getWhitelist().getValues()) {
1371 1449 result.add(getOfflinePlayer((GameProfile) entry.f())); // Should be getKey
1372 1450 }
1373 1451
1374 1452 return result;
1375 1453 }
1376 1454
1455 + @Override
1377 1456 public Set<OfflinePlayer> getOperators() {
1378 1457 Set<OfflinePlayer> result = new HashSet<OfflinePlayer>();
1379 1458
1380 1459 for (JsonListEntry entry : playerList.getOPs().getValues()) {
1381 1460 result.add(getOfflinePlayer((GameProfile) entry.f())); // Should be getKey
1382 1461 }
1383 1462
1384 1463 return result;
1385 1464 }
1386 1465
1466 + @Override
1387 1467 public void reloadWhitelist() {
1388 1468 playerList.reloadWhitelist();
1389 1469 }
1390 1470
1471 + @Override
1391 1472 public GameMode getDefaultGameMode() {
1392 1473 return GameMode.getByValue(console.worlds.get(0).getWorldData().getGameType().a());
1393 1474 }
1394 1475
1476 + @Override
1395 1477 public void setDefaultGameMode(GameMode mode) {
1396 1478 Validate.notNull(mode, "Mode cannot be null");
1397 1479
1398 1480 for (World world : getWorlds()) {
1399 1481 ((CraftWorld) world).getHandle().worldData.setGameType(EnumGamemode.a(mode.getValue()));
1400 1482 }
1401 1483 }
1402 1484
1485 + @Override
1403 1486 public ConsoleCommandSender getConsoleSender() {
1404 1487 return console.console;
1405 1488 }
1406 1489
1407 1490 public EntityMetadataStore getEntityMetadata() {
1408 1491 return entityMetadata;
1409 1492 }
1410 1493
1411 1494 public PlayerMetadataStore getPlayerMetadata() {
1412 1495 return playerMetadata;
1430 1513 entityPlayer.listName = oldName.subSequence(0, oldName.length() - 2 - spaceLeft) + String.valueOf(System.currentTimeMillis() % 99);
1431 1514 } else {
1432 1515 entityPlayer.listName = oldName + String.valueOf(System.currentTimeMillis() % 99);
1433 1516 }
1434 1517
1435 1518 return;
1436 1519 }
1437 1520 }
1438 1521 }
1439 1522
1523 + @Override
1440 1524 public File getWorldContainer() {
1441 1525 if (this.getServer().universe != null) {
1442 1526 return this.getServer().universe;
1443 1527 }
1444 1528
1445 1529 if (container == null) {
1446 1530 container = new File(configuration.getString("settings.world-container", "."));
1447 1531 }
1448 1532
1449 1533 return container;
1450 1534 }
1451 1535
1536 + @Override
1452 1537 public OfflinePlayer[] getOfflinePlayers() {
1453 1538 WorldNBTStorage storage = (WorldNBTStorage) console.worlds.get(0).getDataManager();
1454 1539 String[] files = storage.getPlayerDir().list(new DatFileFilter());
1455 1540 Set<OfflinePlayer> players = new HashSet<OfflinePlayer>();
1456 1541
1457 1542 for (String file : files) {
1458 1543 try {
1459 1544 players.add(getOfflinePlayer(UUID.fromString(file.substring(0, file.length() - 4))));
1460 1545 } catch (IllegalArgumentException ex) {
1461 1546 // Who knows what is in this directory, just ignore invalid files
1462 1547 }
1463 1548 }
1464 1549
1465 - players.addAll(Arrays.asList(getOnlinePlayers()));
1550 + players.addAll(getOnlinePlayers());
1466 1551
1467 1552 return players.toArray(new OfflinePlayer[players.size()]);
1468 1553 }
1469 1554
1555 + @Override
1470 1556 public Messenger getMessenger() {
1471 1557 return messenger;
1472 1558 }
1473 1559
1560 + @Override
1474 1561 public void sendPluginMessage(Plugin source, String channel, byte[] message) {
1475 1562 StandardMessenger.validatePluginMessage(getMessenger(), source, channel, message);
1476 1563
1477 1564 for (Player player : getOnlinePlayers()) {
1478 1565 player.sendPluginMessage(source, channel, message);
1479 1566 }
1480 1567 }
1481 1568
1569 + @Override
1482 1570 public Set<String> getListeningPluginChannels() {
1483 1571 Set<String> result = new HashSet<String>();
1484 1572
1485 1573 for (Player player : getOnlinePlayers()) {
1486 1574 result.addAll(player.getListeningPluginChannels());
1487 1575 }
1488 1576
1489 1577 return result;
1490 1578 }
1491 1579
1492 1580 public void onPlayerJoin(Player player) {
1493 1581 if ((updater.isEnabled()) && (updater.getCurrent() != null) && (player.hasPermission(Server.BROADCAST_CHANNEL_ADMINISTRATIVE))) {
1494 1582 if ((updater.getCurrent().isBroken()) && (updater.getOnBroken().contains(AutoUpdater.WARN_OPERATORS))) {
1495 1583 player.sendMessage(ChatColor.DARK_RED + "The version of CraftBukkit that this server is running is known to be broken. Please consider updating to the latest version at dl.bukkit.org.");
1496 1584 } else if ((updater.isUpdateAvailable()) && (updater.getOnUpdate().contains(AutoUpdater.WARN_OPERATORS))) {
1497 1585 player.sendMessage(ChatColor.DARK_PURPLE + "The version of CraftBukkit that this server is running is out of date. Please consider updating to the latest version at dl.bukkit.org.");
1498 1586 }
1499 1587 }
1500 1588 }
1501 1589
1590 + @Override
1502 1591 public Inventory createInventory(InventoryHolder owner, InventoryType type) {
1503 1592 // TODO: Create the appropriate type, rather than Custom?
1504 1593 return new CraftInventoryCustom(owner, type);
1505 1594 }
1506 1595
1596 + @Override
1507 1597 public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) {
1508 1598 return new CraftInventoryCustom(owner, type, title);
1509 1599 }
1510 1600
1601 + @Override
1511 1602 public Inventory createInventory(InventoryHolder owner, int size) throws IllegalArgumentException {
1512 1603 Validate.isTrue(size % 9 == 0, "Chests must have a size that is a multiple of 9!");
1513 1604 return new CraftInventoryCustom(owner, size);
1514 1605 }
1515 1606
1607 + @Override
1516 1608 public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException {
1517 1609 Validate.isTrue(size % 9 == 0, "Chests must have a size that is a multiple of 9!");
1518 1610 return new CraftInventoryCustom(owner, size, title);
1519 1611 }
1520 1612
1613 + @Override
1521 1614 public HelpMap getHelpMap() {
1522 1615 return helpMap;
1523 1616 }
1524 1617
1525 1618 public SimpleCommandMap getCommandMap() {
1526 1619 return commandMap;
1527 1620 }
1528 1621
1622 + @Override
1529 1623 public int getMonsterSpawnLimit() {
1530 1624 return monsterSpawn;
1531 1625 }
1532 1626
1627 + @Override
1533 1628 public int getAnimalSpawnLimit() {
1534 1629 return animalSpawn;
1535 1630 }
1536 1631
1632 + @Override
1537 1633 public int getWaterAnimalSpawnLimit() {
1538 1634 return waterAnimalSpawn;
1539 1635 }
1540 1636
1637 + @Override
1541 1638 public int getAmbientSpawnLimit() {
1542 1639 return ambientSpawn;
1543 1640 }
1544 1641
1642 + @Override
1545 1643 public boolean isPrimaryThread() {
1546 1644 return Thread.currentThread().equals(console.primaryThread);
1547 1645 }
1548 1646
1647 + @Override
1549 1648 public String getMotd() {
1550 1649 return console.getMotd();
1551 1650 }
1552 1651
1652 + @Override
1553 1653 public WarningState getWarningState() {
1554 1654 return warningState;
1555 1655 }
1556 1656
1557 1657 public List<String> tabComplete(net.minecraft.server.ICommandListener sender, String message) {
1558 1658 if (!(sender instanceof EntityPlayer)) {
1559 1659 return ImmutableList.of();
1560 1660 }
1561 1661
1562 1662 Player player = ((EntityPlayer) sender).getBukkitEntity();
1573 1673 completions = getCommandMap().tabComplete(player, message.substring(1));
1574 1674 } catch (CommandException ex) {
1575 1675 player.sendMessage(ChatColor.RED + "An internal error occurred while attempting to tab-complete this command");
1576 1676 getLogger().log(Level.SEVERE, "Exception when " + player.getName() + " attempted to tab complete " + message, ex);
1577 1677 }
1578 1678
1579 1679 return completions == null ? ImmutableList.<String>of() : completions;
1580 1680 }
1581 1681
1582 1682 public List<String> tabCompleteChat(Player player, String message) {
1583 - Player[] players = getOnlinePlayers();
1584 1683 List<String> completions = new ArrayList<String>();
1585 1684 PlayerChatTabCompleteEvent event = new PlayerChatTabCompleteEvent(player, message, completions);
1586 1685 String token = event.getLastToken();
1587 - for (Player p : players) {
1686 + for (Player p : getOnlinePlayers()) {
1588 1687 if (player.canSee(p) && StringUtil.startsWithIgnoreCase(p.getName(), token)) {
1589 1688 completions.add(p.getName());
1590 1689 }
1591 1690 }
1592 1691 pluginManager.callEvent(event);
1593 1692
1594 1693 Iterator<?> it = completions.iterator();
1595 1694 while (it.hasNext()) {
1596 1695 Object current = it.next();
1597 1696 if (!(current instanceof String)) {
1598 1697 // Sanity
1599 1698 it.remove();
1600 1699 }
1601 1700 }
1602 1701 Collections.sort(completions, String.CASE_INSENSITIVE_ORDER);
1603 1702 return completions;
1604 1703 }
1605 1704
1705 + @Override
1606 1706 public CraftItemFactory getItemFactory() {
1607 1707 return CraftItemFactory.instance();
1608 1708 }
1609 1709
1710 + @Override
1610 1711 public CraftScoreboardManager getScoreboardManager() {
1611 1712 return scoreboardManager;
1612 1713 }
1613 1714
1614 1715 public void checkSaveState() {
1615 1716 if (this.playerCommandState || this.printSaveWarning || this.console.autosavePeriod <= 0) {
1616 1717 return;
1617 1718 }
1618 1719 this.printSaveWarning = true;
1619 1720 getLogger().log(Level.WARNING, "A manual (plugin-induced) save has been detected while server is configured to auto-save. This may affect performance.", warningState == WarningState.ON ? new Throwable() : null);
1647 1748 ByteBuf bytebuf = Unpooled.buffer();
1648 1749
1649 1750 Validate.isTrue(image.getWidth() == 64, "Must be 64 pixels wide");
1650 1751 Validate.isTrue(image.getHeight() == 64, "Must be 64 pixels high");
1651 1752 ImageIO.write(image, "PNG", new ByteBufOutputStream(bytebuf));
1652 1753 ByteBuf bytebuf1 = Base64.encode(bytebuf);
1653 1754
1654 1755 return new CraftIconCache("data:image/png;base64," + bytebuf1.toString(Charsets.UTF_8));
1655 1756 }
1656 1757
1758 + @Override
1657 1759 public void setIdleTimeout(int threshold) {
1658 1760 console.setIdleTimeout(threshold);
1659 1761 }
1660 1762
1763 + @Override
1661 1764 public int getIdleTimeout() {
1662 1765 return console.getIdleTimeout();
1663 1766 }
1664 1767
1665 1768 @Deprecated
1666 1769 @Override
1667 1770 public UnsafeValues getUnsafe() {
1668 1771 return CraftMagicNumbers.INSTANCE;
1669 1772 }
1670 1773 }

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut