package com.alecgorge.minecraft.jsonapi.chat; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.entity.*; import org.bukkit.entity.Entity; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerChatEvent; import com.alecgorge.minecraft.jsonapi.JSONAPI; import com.alecgorge.minecraft.jsonapi.util.OfflinePlayerLoader; //#ifdefined mcversion //$import net.minecraft.server./*$mcversion$*/.*; //$import org.bukkit.craftbukkit./*$mcversion$*/.*; //$import org.bukkit.craftbukkit./*$mcversion$*/.entity.*; //$import org.bukkit.craftbukkit./*$mcversion$*/.util.*; //#else import net.minecraft.server.v1_11_R1.*; import org.bukkit.craftbukkit.v1_11_R1.*; import org.bukkit.craftbukkit.v1_11_R1.entity.*; import org.bukkit.craftbukkit.v1_11_R1.util.*; //#endif @SuppressWarnings("deprecation") public class BukkitRealisticChat implements IRealisticChat { private Server Server = JSONAPI.instance.getServer(); public Server getServer() { return Server; } public class FauxPlayer extends CraftPlayer { String name = null; UUID fakeUUID = null; public FauxPlayer(String fakeName, UUID fakeUUID, CraftPlayer player) { super((CraftServer)player.getServer(), player.getHandle()); name = fakeName; this.fakeUUID = fakeUUID; } @Override public String getName() { if(name == null) { return super.getName(); } return name; } @Override public String getDisplayName() { if(name == null) { return super.getDisplayName(); } return name; } @Override public UUID getUniqueId() { if(fakeUUID == null) { return super.getUniqueId(); } return super.getUniqueId(); } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @return damage taken since the last no damage ticks time period */ @Override public int _INVALID_getLastDamage() { return 0; } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @param damage amount of damage */ @Override public void _INVALID_setLastDamage(int damage) { } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @param amount Amount of damage to deal */ @Override public void _INVALID_damage(int amount) { } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @param amount Amount of damage to deal * @param source Entity which to attribute this damage from */ @Override public void _INVALID_damage(int amount, Entity source) { } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @return Health represented from 0 to max */ @Override public int _INVALID_getHealth() { return 0; } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @param health New health represented from 0 to max * @throws IllegalArgumentException Thrown if the health is {@literal < 0 or >} * {@link #getMaxHealth()} */ @Override public void _INVALID_setHealth(int health) { } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @return Maximum health */ @Override public int _INVALID_getMaxHealth() { return 0; } /** * This method exists for legacy reasons to provide backwards * compatibility. It will not exist at runtime and should not be used * under any circumstances. * * @param health amount of health to set the maximum to */ @Override public void _INVALID_setMaxHealth(int health) { } } public boolean chatWithNameForPlayer(String message, String name, String playerToExtend) { Player player = getServer().getPlayerExact(name); // player isn't online if (player == null) { player = JSONAPI.loadOfflinePlayer(name); } // player doesn't exist. better fake something. if (player == null) { Player pe = null; FauxPlayer f = null; if(getServer().getOfflinePlayers().length > 0) { pe = OfflinePlayerLoader.loadFromOfflinePlayer(getServer().getOfflinePlayers()[0]); } else if(getServer().getOnlinePlayers().size() > 0) { pe = getServer().getOnlinePlayers().iterator().next(); } if(playerToExtend == null) { f = new FauxPlayer(name, UUID.randomUUID(), (CraftPlayer)pe); } else { f = new FauxPlayer(name, UUID.randomUUID(), (CraftPlayer)pe); } return chatWithPlayer(message, f); } return chatWithPlayer(message, player); } public boolean chatWithName(String message, String name) { return chatWithNameForPlayer(message, name, null); } public void pluginDisable() { } @Override public boolean canHandleChats() { return true; } public boolean chatWithPlayer(String message, Player player) { try { String s = message; boolean async = false; // based on // net/minecraft/server/v1_9_R1/PlayerConnection.java#chat(String, boolean) final MinecraftServer minecraftServer; if (getServer() instanceof CraftServer) { minecraftServer = ((CraftServer) getServer()).getServer(); } else { System.err.println("Whoa, getServer() isn't a CraftServer?! I can't send a chat message now! It is a " + getServer().getClass().getCanonicalName()); return false; } AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer)); getServer().getPluginManager().callEvent(event); Waitable<Void> waitable; if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); queueEvent.setCancelled(event.isCancelled()); waitable = new Waitable<Void>() { protected Void evaluate() { Bukkit.getPluginManager().callEvent(queueEvent); if (queueEvent.isCancelled()) { return null; } String message = String.format(queueEvent.getFormat(), new Object[] { queueEvent.getPlayer().getDisplayName(),queueEvent.getMessage() }); minecraftServer.console.sendMessage(message); if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { for (EntityPlayer player : (List<EntityPlayer>) minecraftServer.getPlayerList().players) { player.sendMessage(CraftChatMessage.fromString(message)); } } else { for (Player player : queueEvent.getRecipients()) { player.sendMessage(message); } } return null; } }; if (async) minecraftServer.processQueue.add(waitable); else waitable.run(); try { waitable.get(); } catch (InterruptedException localInterruptedException) { Thread.currentThread().interrupt(); } catch (ExecutionException e) { throw new RuntimeException("Exception processing chat event", e.getCause()); } } else { if (event.isCancelled()) { JSONAPI.dbug("Chat event cancelled"); return false; } s = String.format(event.getFormat(), new Object[] { event.getPlayer().getDisplayName(),event.getMessage() }); minecraftServer.console.sendMessage(s); if (((LazyPlayerSet) event.getRecipients()).isLazy()) { for (EntityPlayer recipient : (List<EntityPlayer>) minecraftServer.getPlayerList().players) { recipient.sendMessage(CraftChatMessage.fromString(s)); } } else { for (Player p : event.getRecipients()) { p.sendMessage(message); } } } return true; } catch (Exception e) { e.printStackTrace(); return false; } } }