-
-
Save TigerHix/b19e588601271d100fe9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.comphenix.example; | |
import java.util.Arrays; | |
import org.bukkit.ChatColor; | |
import org.bukkit.command.Command; | |
import org.bukkit.command.CommandSender; | |
import org.bukkit.entity.Player; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import com.comphenix.protocol.events.ListenerPriority; | |
import com.google.common.base.Joiner; | |
// Test plugin | |
public class ExampleMod extends JavaPlugin { | |
private LookupNameManager manager; | |
@Override | |
public void onEnable() { | |
manager = new LookupNameManager(this); | |
manager.start(ListenerPriority.NORMAL); | |
} | |
@Override | |
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { | |
if (args.length < 2) { | |
sender.sendMessage(ChatColor.RED + "Must specify target player and new name."); | |
return true; | |
} | |
@SuppressWarnings("deprecation") | |
Player target = getServer().getPlayer(args[0]); | |
String name = Joiner.on(" ").join(Arrays.copyOfRange(args, 1, args.length)); | |
if (target == null) { | |
sender.sendMessage(ChatColor.RED + "Cannot find player '" + args[0] + "'"); | |
return true; | |
} | |
manager.setGlobalName(target, name); | |
sender.sendMessage(ChatColor.YELLOW + "Renamed " + target + " to " + name); | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.comphenix.example; | |
import java.util.Map; | |
import org.bukkit.entity.Player; | |
import org.bukkit.event.EventHandler; | |
import org.bukkit.event.HandlerList; | |
import org.bukkit.event.Listener; | |
import org.bukkit.event.player.PlayerQuitEvent; | |
import org.bukkit.plugin.Plugin; | |
import com.comphenix.protocol.events.ListenerPriority; | |
import com.google.common.base.Objects; | |
import com.google.common.base.Preconditions; | |
import com.google.common.collect.HashBasedTable; | |
import com.google.common.collect.Maps; | |
import com.google.common.collect.Table; | |
public class LookupNameManager extends NameManager { | |
// Observing Client -> Entity -> Name | |
private Table<String, String, String> clientName = HashBasedTable.create(); | |
// Fallback name in case the per-client name is missing | |
private Map<String, String> globalName = Maps.newHashMap(); | |
// Remove outdated entries | |
protected boolean autoCleanup = true; | |
protected Listener bukkitListener; | |
/** | |
* Construct a new lookup handler. | |
* @param manager - the name manager. | |
*/ | |
public LookupNameManager(Plugin plugin) { | |
super(plugin); | |
} | |
/** | |
* Start the handler and the associated name mananger. | |
* @param priority - the listener priority. | |
*/ | |
public void start(ListenerPriority priority) { | |
super.start(priority); | |
registerBukkit(); | |
} | |
private void registerBukkit() { | |
Plugin owner = getPlugin(); | |
owner.getServer().getPluginManager().registerEvents(bukkitListener = new Listener() { | |
@EventHandler | |
public void onPlayerQuit(PlayerQuitEvent e) { | |
if (!autoCleanup) | |
return; | |
// Clean up table | |
String removed = e.getPlayer().getName(); | |
clientName.rowKeySet().remove(removed); | |
clientName.columnKeySet().remove(removed); | |
globalName.remove(removed); | |
} | |
}, owner); | |
} | |
/** | |
* Invoked when we're intercepting the name of an observed entity. | |
* @param client - the client that is receiving the name. | |
* @param observedEntity - the entity whose name we are sending. | |
* @param observedName - the current name of the entity. | |
* @return The new name of the entity. Use NULL for no change. | |
*/ | |
public final String handleName(Player client, Player observedEntity, String observedName) { | |
String changed = clientName.get(client.getName(), observedEntity.getName()); | |
// Fall back to the global name change | |
if (changed == null) { | |
changed = globalName.get(observedEntity.getName()); | |
} | |
return changed; | |
} | |
/** | |
* Set the global name of a given entity. | |
* <p> | |
* This will be overridden by {@link #setClientName(Player, Player, String)} for individual clients. | |
* @param observedEntity - the player entity to rename. | |
* @param observedName - the new name of this entity. | |
* @return The previous altered name, or NULL. | |
*/ | |
public String setGlobalName(Player observedEntity, String observedName) { | |
checkGlobal(observedEntity); | |
String original = globalName.put(observedEntity.getName(), observedName); | |
// See if we need to update the entity | |
if (!Objects.equal(original, observedName)) | |
updateEntity(null, observedEntity); | |
return original; | |
} | |
/** | |
* Set the visible name of a player entity for a given client. | |
* @param client - the client that will see the name change. | |
* @param observedEntity - the player entity to rename. | |
* @param observedName - the new name of this entity. | |
* @return The previous altered name, or NULL. | |
*/ | |
public String setClientName(Player client, Player observedEntity, String observedName) { | |
checkClient(client, observedEntity); | |
String original = clientName.put(client.getName(), | |
observedEntity.getName(), observedName); | |
// See if we need to update the entity | |
if (!Objects.equal(original, observedName)) | |
updateEntity(client, observedEntity); | |
return original; | |
} | |
/** | |
* Reset the visible name of an entity to the default globally. | |
* @param observedEntity - the entity whose name will be reset. | |
* @return The removed custom name, or NULL. | |
*/ | |
public String resetGlobalName(Player observedEntity) { | |
checkGlobal(observedEntity); | |
String removed = globalName.remove(observedEntity.getName()); | |
// Trigger a name update | |
if (removed != null) | |
updateEntity(null, observedEntity); | |
return removed; | |
} | |
/** | |
* Reset the visible name of an entity to the default for a client. | |
* @param client - the client we're resetting. | |
* @param observedEntity - the entity whose name will be reset. | |
* @return The removed custom name, or NULL. | |
*/ | |
public String resetClientName(Player client, Player observedEntity) { | |
checkClient(client, observedEntity); | |
String removed = clientName.remove(client.getName(), observedEntity.getName()); | |
// Trigger a name update | |
if (removed != null) | |
updateEntity(client, observedEntity); | |
return removed; | |
} | |
// Throw on NULL | |
private void checkGlobal(Player observedEntity) { | |
if (!isStarted()) | |
throw new IllegalStateException("Name mananger hasn't started yet."); | |
Preconditions.checkNotNull(observedEntity, "observedEntity cannot be NULL"); | |
} | |
// Here too | |
private void checkClient(Player client, Player observedEntity) { | |
Preconditions.checkNotNull(client, "client cannot be NULL"); | |
checkGlobal(observedEntity); | |
} | |
/** | |
* Determine if this handler has started. | |
* @return TRUE if it has, FALSE otherwise. | |
*/ | |
public boolean isStarted() { | |
return bukkitListener != null && super.isStarted(); | |
} | |
/** | |
* Determine if we automatically remove logged out entires. | |
* @return TRUE if we do, FALSE otherwise. | |
*/ | |
public boolean isAutoCleanup() { | |
return autoCleanup; | |
} | |
/** | |
* Set whether or not we automatically remove entries of logged out players. | |
* @param autoCleanup - TRUE to auto-clean, FALSE otherwise. | |
*/ | |
public void setAutoCleanup(boolean autoCleanup) { | |
this.autoCleanup = autoCleanup; | |
} | |
/** | |
* Close the current lookup handler and the associated manager. | |
*/ | |
public void close() { | |
if (isStarted()) { | |
HandlerList.unregisterAll(bukkitListener); | |
super.close(); | |
bukkitListener = null; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.comphenix.example; | |
import java.util.Arrays; | |
import java.util.List; | |
import org.apache.commons.lang.StringUtils; | |
import org.bukkit.entity.Player; | |
import org.bukkit.plugin.Plugin; | |
import com.comphenix.protocol.PacketType; | |
import com.comphenix.protocol.ProtocolLibrary; | |
import com.comphenix.protocol.ProtocolManager; | |
import com.comphenix.protocol.events.ListenerPriority; | |
import com.comphenix.protocol.events.PacketAdapter; | |
import com.comphenix.protocol.events.PacketEvent; | |
import com.comphenix.protocol.utility.MinecraftReflection; | |
import com.comphenix.protocol.wrappers.WrappedGameProfile; | |
import com.google.common.base.Preconditions; | |
/** | |
* Represents a name manager. | |
* @author Kristian | |
*/ | |
public abstract class NameManager { | |
protected ProtocolManager manager; | |
// Listeners | |
protected PacketAdapter packetListener; | |
// The parent plugin | |
protected final Plugin plugin; | |
/** | |
* Construct a new player renamer. | |
* @param plugin - the plugin. | |
*/ | |
public NameManager(Plugin plugin) { | |
this.plugin = Preconditions.checkNotNull(plugin, "plugin cannot be NULL."); | |
} | |
/** | |
* Start the player renamer component. | |
* @param priority - the priority of our player modification. | |
*/ | |
public void start(ListenerPriority priority) { | |
if (isStarted()) { | |
throw new IllegalStateException("Cannot start renamer twice."); | |
} | |
registerProtocolLib(priority); | |
} | |
private void registerProtocolLib(ListenerPriority priority) { | |
this.manager = ProtocolLibrary.getProtocolManager(); | |
manager.addPacketListener(packetListener = | |
new PacketAdapter(plugin, priority, PacketType.Play.Server.NAMED_ENTITY_SPAWN) { | |
@Override | |
public void onPacketSending(PacketEvent event) { | |
Player observed = (Player) event.getPacket().getEntityModifier(event).read(0); | |
// Determine if we are | |
if (MinecraftReflection.isUsingNetty()) { | |
handleNetty(event, observed); | |
} else { | |
handleLegacy(event, observed); | |
} | |
} | |
}); | |
} | |
/** | |
* Process a spawn player packet in version 1.7.2 and above. | |
* @param event - the packet event. | |
* @param observed - the observed player entity. | |
*/ | |
private void handleNetty(PacketEvent event, Player observed) { | |
WrappedGameProfile profile = event.getPacket().getGameProfiles().read(0); | |
String name = handleName(event.getPlayer(), observed, profile.getName()); | |
// Update the displayed name | |
if (name != null) { | |
event.getPacket().getGameProfiles().write(0, profile.withName(StringUtils.abbreviate(name, 16))); | |
} | |
} | |
// As above, only for 1.6.4 and below | |
private void handleLegacy(PacketEvent event, Player observed) { | |
String name = handleName(event.getPlayer(), observed, event.getPacket().getStrings().read(0)); | |
// As above | |
if (name != null) { | |
event.getPacket().getStrings().write(0, StringUtils.abbreviate(name, 16)); | |
} | |
} | |
/** | |
* Trigger an entity update. | |
* @param client - the client that will recieve the update. | |
* @param observerEntity - the observed entity to update. | |
*/ | |
protected void updateEntity(Player client, Player observerEntity) { | |
// A list of the players we will update | |
List<Player> trackers = client != null ? | |
Arrays.asList(client) : manager.getEntityTrackers(observerEntity); | |
manager.updateEntity(observerEntity, trackers); | |
} | |
/** | |
* Invoked when we're intercepting the name of an observed entity. | |
* @param client - the client that is receiving the name. | |
* @param observedEntity - the entity whose name we are sending. | |
* @param observedName - the current name of the entity. | |
* @return The new name of the entity. Use NULL for no change. | |
*/ | |
public abstract String handleName(Player client, Player observedEntity, String observedName); | |
/** | |
* Retrieve the owner plugin. | |
* @return The owner. | |
*/ | |
public Plugin getPlugin() { | |
return plugin; | |
} | |
/** | |
* Determine if we're currently renaming players. | |
* @return TRUE if we are, FALSE otherwise. | |
*/ | |
public boolean isStarted() { | |
return packetListener != null; | |
} | |
public void close() { | |
if (packetListener != null) { | |
manager.removePacketListener(packetListener); | |
packetListener = null; | |
packetListener = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment