Compare commits

...
10 Commits
Author SHA1 Message Date
Andre_601 c8acb4d90a Merge pull request #36 from Andre601/feature/unified-eventhandler
Create unified EventHandler
2022-12-08 21:56:48 +01:00
Andre_601 5575243a79 Merge pull request #35 from Andre601/dependabot/maven/core/com.google.code.gson-gson-2.10
Bump gson from 2.9.1 to 2.10 in /core
2022-12-08 16:43:13 +01:00
Andre601 4cd4aeb12a Move Favicon creation and logging to PingEventHandler 2022-12-08 16:42:23 +01:00
Andre601 5922b2235e Bump version 2022-12-07 21:19:23 +01:00
Andre601 2fcef08f5a Wrap up (no pun intended) remaining platform events 2022-12-07 16:28:39 +01:00
Andre601 30c28b07a4 Smaller changes 2022-12-06 21:32:16 +01:00
Andre601 08b4f1029c Make Protocol and ServerPing final 2022-12-06 21:27:09 +01:00
Andre601 f5051022aa Create unified EventHandler 2022-12-06 21:24:43 +01:00
dependabot[bot] fe51e78764 Bump gson from 2.9.1 to 2.10 in /core
Bumps [gson](https://github.com/google/gson) from 2.9.1 to 2.10.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.9.1...gson-parent-2.10)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-06 15:11:07 +00:00
Andre_601 5b2d9d910f Use env variables 2022-12-06 14:17:34 +01:00
14 changed files with 851 additions and 418 deletions

No files matched your search

+2 -2
View File
@@ -81,12 +81,12 @@ jobs:
id: github-release
run: |
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
echo "::set-output name=version::$version"
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
uses: Kir-Antipov/mc-publish@v3.2
with:
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
version: ${{ steps.github-release.outputs.version }}
version: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
version-type: release
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
files-secondary: ""
@@ -0,0 +1,156 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ProxyPingEvent;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Favicon>{
private final BungeeCordCore plugin;
private final ProxyPingEvent event;
private final ServerPing.Protocol protocol;
private final ServerPing ping;
public BungeeEventWrapper(BungeeCordCore plugin, ProxyPingEvent event){
this.plugin = plugin;
this.event = event;
this.protocol = event.getResponse().getVersion();
this.ping = event.getResponse();
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.getPlayers().setMax(maxPlayers);
}
@Override
public void setMotd(Component component){
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
}
@Override
public void hidePlayers(){
ping.setPlayers(null);
}
@Override
public void setPlayerCount(String name){
protocol.setName(name);
protocol.setProtocol(-1);
}
@Override
public void setPlayers(List<String> players, GenericPlayer<ProxiedPlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(players, playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.PlayerInfo[0]);
if(playerInfos.length > 0)
ping.getPlayers().setSample(playerInfos);
}
@Override
public void setFavicon(Favicon favicon){
ping.setFavicon(favicon);
}
@Override
public void setDefaultFavicon(){
ping.setFavicon(ping.getFaviconObject());
}
@Override
public void updateEvent(){
this.ping.setVersion(this.protocol);
this.event.setResponse(this.ping);
}
@Override
public boolean isInvalidProtocol(){
return protocol == null;
}
@Override
public int getProtocolVersion(){
return this.protocol.getProtocol();
}
@Override
public int getOnlinePlayers(){
return ping.getPlayers().getOnline();
}
@Override
public int getMaxPlayers(){
return ping.getPlayers().getMax();
}
@Override
public String getPlayerIP(){
return ((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<ProxiedPlayer> player){
return text;
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getConnection().getVirtualHost());
}
@Override
public PluginCore<Favicon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<ProxiedPlayer> createPlayer(String name, int protocol){
return new BungeePlayer(name, protocol);
}
@Override
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
}
@@ -26,24 +26,12 @@
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.TextComponent;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import java.net.InetSocketAddress;
public class PingEvent implements Listener{
private final BungeeCordCore plugin;
@@ -55,91 +43,6 @@ public class PingEvent implements Listener{
@EventHandler(priority = EventPriority.LOW)
public void onProxyPing(ProxyPingEvent event){
ServerPing ping = event.getResponse();
ServerPing.Protocol protocol = ping.getVersion();
if(protocol == null)
return;
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(
((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString()
);
InetSocketAddress host = event.getConnection().getVirtualHost();
int online = ping.getPlayers().getOnline();
int max = ping.getPlayers().getMax();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new BungeePlayer(playerName, protocol.getProtocol()));
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
ping.getPlayers().setMax(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
TextComponent component = new TextComponent(BungeeComponentSerializer.get().serialize(
ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toComponent()
));
ping.setDescriptionComponent(component);
}
if(profile.shouldHidePlayers()){
ping.setPlayers(null);
}
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
protocol.setName(ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString()
);
protocol.setProtocol(-1);
}
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.PlayerInfo[0]);
if(playerInfos.length > 0)
ping.getPlayers().setSample(playerInfos);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Favicon.create(image);
}catch(Exception ex){
plugin.getPluginLogger().warn("Unable to create Favicon. %s", ex.getMessage());
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
ping.setFavicon(ping.getFaviconObject());
}else{
ping.setFavicon(favicon);
}
}
ping.setVersion(protocol);
event.setResponse(ping);
PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
}
}
+1 -1
View File
@@ -73,7 +73,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
<version>2.10</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
@@ -173,7 +173,9 @@ public class UpdateChecker{
}
public static class ModrinthVersion{
@SuppressWarnings("FieldMayBeFinal")
private String id;
@SuppressWarnings("FieldMayBeFinal")
private String versionNumber;
public ModrinthVersion(String id, String versionNumber){
@@ -0,0 +1,122 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.events;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
public class PingEventHandler{
public static <P, F> void handleEvent(GenericEventWrapper<P, F> event){
if(event.isInvalidProtocol())
return;
PluginCore<F> plugin = event.getPlugin();
GenericPlayer<P> player = event.createPlayer(
plugin.getCore().getPlayerHandler().getPlayerByIp(event.getPlayerIP()),
event.getProtocolVersion()
);
String host = event.getVirtualHost();
int online = event.getOnlinePlayers();
int max = event.getMaxPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host);
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
event.setMaxPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host);
if(!profile.getMotd().isEmpty()){
event.setMotd(
ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toComponent()
);
}
if(profile.shouldHidePlayers()){
event.hidePlayers();
}
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
event.setPlayerCount(
ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toString()
);
}
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
event.setPlayers(profile.getPlayers(), player, playerPlaceholders, serverPlaceholders);
}
if(!profile.getFavicon().isEmpty()){
String favicon = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
F fav = plugin.getFaviconHandler().getFavicon(favicon, image -> {
try{
return event.createFavicon(image);
}catch(Exception ex){
plugin.getPluginLogger().warn("Encountered an Exception while creating Favicon!", ex);
return null;
}
});
if(fav == null){
event.setDefaultFavicon();
}else{
event.setFavicon(fav);
}
}
event.updateEvent();
}
}
@@ -0,0 +1,79 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.events;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.Component;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
public interface GenericEventWrapper<P, F>{
void setMaxPlayers(int maxPlayers);
void setMotd(Component component);
void hidePlayers();
void setPlayerCount(String name);
void setPlayers(List<String> players, GenericPlayer<P> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders);
void setFavicon(F favicon);
void setDefaultFavicon();
void updateEvent();
boolean isInvalidProtocol();
int getProtocolVersion();
int getOnlinePlayers();
int getMaxPlayers();
String getPlayerIP();
String parsePAPIPlaceholders(String text, GenericPlayer<P> player);
String getVirtualHost();
PluginCore<F> getPlugin();
GenericPlayer<P> createPlayer(String name, int protocol);
F createFavicon(BufferedImage image) throws Exception;
default String resolveHost(InetSocketAddress address){
return address == null ? null : address.getHostString();
}
}
@@ -0,0 +1,160 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.PaperPlayer;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.util.CachedServerIcon;
import java.awt.image.BufferedImage;
import java.util.List;
public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, CachedServerIcon>{
private final PaperCore plugin;
private final PaperServerListPingEvent event;
public PaperEventWrapper(PaperCore plugin, PaperServerListPingEvent event){
this.plugin = plugin;
this.event = event;
}
@Override
public void setMaxPlayers(int maxPlayers){
event.setMaxPlayers(maxPlayers);
}
@Override
public void setMotd(Component component){
event.motd(component);
}
@Override
public void hidePlayers(){
event.setHidePlayers(true);
}
@Override
public void setPlayerCount(String name){
event.setVersion(name);
event.setProtocolVersion(-1);
}
@Override
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
event.getPlayerSample().clear();
event.getPlayerSample().addAll(
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
@Override
public void setFavicon(CachedServerIcon favicon){
event.setServerIcon(favicon);
}
@Override
public void setDefaultFavicon(){
event.setServerIcon(event.getServerIcon());
}
// Not used in Paper
@Override
public void updateEvent(){}
// Not used in Paper
@Override
public boolean isInvalidProtocol(){
return false;
}
@Override
public int getProtocolVersion(){
return event.getClient().getProtocolVersion();
}
@Override
public int getOnlinePlayers(){
return event.getNumPlayers();
}
@Override
public int getMaxPlayers(){
return event.getMaxPlayers();
}
@Override
public String getPlayerIP(){
return event.getClient().getAddress().getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getClient().getVirtualHost());
}
@Override
public PluginCore<CachedServerIcon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
OfflinePlayer player = Bukkit.getPlayerExact(name);
if(player == null){
player = Bukkit.getOfflinePlayer(name);
return new PaperPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
}
return new PaperPlayer(player, name, protocol);
}
@Override
public CachedServerIcon createFavicon(BufferedImage image) throws Exception{
return Bukkit.loadServerIcon(image);
}
}
@@ -25,23 +25,11 @@
package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.PaperPlayer;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.util.CachedServerIcon;
import java.net.InetSocketAddress;
public class PingEvent implements Listener{
@@ -54,101 +42,6 @@ public class PingEvent implements Listener{
@EventHandler
public void onServerPing(PaperServerListPingEvent event){
InetSocketAddress address = event.getClient().getAddress();
InetSocketAddress host = event.getClient().getVirtualHost();
PaperPlayer player = resolvePlayer(address, event.getClient().getProtocolVersion());
int online = event.getNumPlayers();
int max = event.getMaxPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
event.setMaxPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
event.motd(ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toComponent());
}
if(profile.shouldHidePlayers()){
event.setHidePlayers(true);
}
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
event.setVersion(ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString());
event.setProtocolVersion(-1);
}
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
event.getPlayerSample().clear();
event.getPlayerSample().addAll(
plugin.createPlayers(profile.getPlayers(), player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
CachedServerIcon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Bukkit.loadServerIcon(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
event.setServerIcon(event.getServerIcon());
}else{
event.setServerIcon(favicon);
}
}
}
private PaperPlayer resolvePlayer(InetSocketAddress address, int protocol){
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
if(player == null){
player = Bukkit.getOfflinePlayer(playerName);
return new PaperPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
}
return new PaperPlayer(player, playerName, protocol);
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
}
}
+1 -1
View File
@@ -12,7 +12,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.version>1.7.0</plugin.version>
<plugin.version>1.8.0</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<maven.compiler.source>16</maven.compiler.source>
@@ -25,25 +25,13 @@
package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
import com.comphenix.protocol.PacketType;
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.wrappers.AdventureComponentConverter;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.Listener;
import java.net.InetSocketAddress;
@@ -52,13 +40,11 @@ import java.util.Map;
public class PingEvent implements Listener{
private final SpigotCore plugin;
private final ProtocolManager protocolManager;
private final Map<String, String> hostAddresses = new HashMap<>();
public PingEvent(SpigotCore plugin, ProtocolManager protocolManager){
this.plugin = plugin;
this.protocolManager = protocolManager;
loadPacketListener(plugin);
@@ -81,106 +67,8 @@ public class PingEvent implements Listener{
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
@Override
public void onPacketSending(PacketEvent event){
WrappedServerPing ping = event.getPacket().getServerPings().read(0);
InetSocketAddress address = event.getPlayer().getAddress();
if(address == null)
return;
SpigotPlayer player = resolvePlayer(address, ping.getVersionProtocol());
int online = ping.getPlayersOnline();
int max = ping.getPlayersMaximum();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
ServerListProfile profile = ProfileManager.get(spigotPlugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
ping.setPlayersMaximum(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
if(!profile.getMotd().isEmpty()){
Component component = ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toComponent();
ping.setMotD(AdventureComponentConverter.fromComponent(component));
}
if(profile.shouldHidePlayers()){
ping.setPlayersVisible(false);
}
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
ping.setVersionName(ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString()
);
ping.setVersionProtocol(-1);
}
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
ping.setPlayers(
spigotPlugin.createPlayers(profile.getPlayers(), player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
WrappedServerPing.CompressedImage favicon = spigotPlugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return WrappedServerPing.CompressedImage.fromPng(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
spigotPlugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
ping.setFavicon(ping.getFavicon());
}else{
ping.setFavicon(favicon);
}
}
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event, hostAddresses));
}
});
}
private SpigotPlayer resolvePlayer(InetSocketAddress address, int protocol){
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
if(player == null){
//noinspection deprecation
player = Bukkit.getOfflinePlayer(playerName);
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
}
return new SpigotPlayer(player, playerName, protocol);
}
}
@@ -0,0 +1,170 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Map;
public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlayer, WrappedServerPing.CompressedImage>{
private final SpigotCore plugin;
private final PacketEvent event;
private final WrappedServerPing ping;
private final Map<String, String> hostAddresses;
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event, Map<String, String> hostAddresses){
this.plugin = plugin;
this.event = event;
this.ping = event.getPacket().getServerPings().read(0);
this.hostAddresses = hostAddresses;
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.setPlayersMaximum(maxPlayers);
}
@Override
public void setMotd(Component component){
ping.setMotD(AdventureComponentConverter.fromComponent(component));
}
@Override
public void hidePlayers(){
ping.setPlayersVisible(false);
}
@Override
public void setPlayerCount(String name){
ping.setVersionName(name);
ping.setVersionProtocol(-1);
}
@Override
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ping.setPlayers(
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
@Override
public void setFavicon(WrappedServerPing.CompressedImage favicon){
ping.setFavicon(favicon);
}
@Override
public void setDefaultFavicon(){
ping.setFavicon(ping.getFavicon());
}
// Not used in ProtocolLib
@Override
public void updateEvent(){}
@Override
public boolean isInvalidProtocol(){
return event.getPlayer().getAddress() == null;
}
@Override
public int getProtocolVersion(){
return ping.getVersionProtocol();
}
@Override
public int getOnlinePlayers(){
return ping.getPlayersOnline();
}
@Override
public int getMaxPlayers(){
return ping.getPlayersMaximum();
}
@Override
public String getPlayerIP(){
return event.getPlayer().getAddress() == null ? "UNKNOWN" : event.getPlayer().getAddress().getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
}
@Override
public String getVirtualHost(){
String host = this.resolveHost(event.getPlayer().getAddress());
if(host == null)
return null;
return hostAddresses.get(host);
}
@Override
public PluginCore<WrappedServerPing.CompressedImage> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
OfflinePlayer player = Bukkit.getPlayerExact(name);
if(player == null){
//noinspection deprecation
player = Bukkit.getOfflinePlayer(name);
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
}
return new SpigotPlayer(player, name, protocol);
}
@Override
public WrappedServerPing.CompressedImage createFavicon(BufferedImage image) throws Exception{
return WrappedServerPing.CompressedImage.fromPng(image);
}
}
@@ -25,22 +25,11 @@
package ch.andre601.advancedserverlist.velocity.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import java.net.InetSocketAddress;
import java.util.List;
public class PingEvent{
@@ -53,85 +42,6 @@ public class PingEvent{
@Subscribe(order = PostOrder.EARLY)
public void onProxyPing(ProxyPingEvent event){
ServerPing ping = event.getPing();
ServerPing.Version protocol = ping.getVersion();
if(protocol == null)
return;
ServerPing.Builder builder = ping.asBuilder();
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(event.getConnection().getRemoteAddress().getHostString());
InetSocketAddress host = event.getConnection().getVirtualHost().orElse(null);
int online = builder.getOnlinePlayers();
int max = builder.getMaximumPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new VelocityPlayer(playerName, protocol.getProtocol()));
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
builder.maximumPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
List<String> motd = profile.getMotd();
builder.description(ComponentParser.list(motd)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toComponent()
);
}
if(profile.shouldHidePlayers()){
builder.nullPlayers();
}
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
builder.version(new ServerPing.Version(
-1,
ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString()
));
}
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
ServerPing.SamplePlayer[] playerSamples = plugin.createPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.SamplePlayer[0]);
if(playerSamples.length > 0)
builder.clearSamplePlayers().samplePlayers(playerSamples);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Favicon.create(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
}else{
builder.favicon(favicon);
}
}
event.setPing(builder.build());
PingEventHandler.handleEvent(new VelocityEventWrapper(plugin, event));
}
}
@@ -0,0 +1,150 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.velocity.events;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import net.kyori.adventure.text.Component;
import java.awt.image.BufferedImage;
import java.util.List;
public class VelocityEventWrapper implements GenericEventWrapper<Player, Favicon>{
private final VelocityCore plugin;
private final ProxyPingEvent event;
private final ServerPing.Builder builder;
private final ServerPing.Version protocol;
public VelocityEventWrapper(VelocityCore plugin, ProxyPingEvent event){
this.plugin = plugin;
this.event = event;
this.builder = event.getPing().asBuilder();
this.protocol = event.getPing().getVersion();
}
@Override
public void setMaxPlayers(int maxPlayers){
builder.maximumPlayers(maxPlayers);
}
@Override
public void setMotd(Component component){
builder.description(component);
}
@Override
public void hidePlayers(){
builder.nullPlayers();
}
@Override
public void setPlayerCount(String name){
builder.version(new ServerPing.Version(-1, name));
}
@Override
public void setPlayers(List<String> players, GenericPlayer<Player> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ServerPing.SamplePlayer[] playerSamples = plugin.createPlayers(players, playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.SamplePlayer[0]);
if(playerSamples.length > 0)
builder.clearSamplePlayers().samplePlayers(playerSamples);
}
@Override
public void setFavicon(Favicon favicon){
builder.favicon(favicon);
}
// Not used in Velocity
@Override
public void setDefaultFavicon(){}
@Override
public void updateEvent(){
event.setPing(builder.build());
}
@Override
public boolean isInvalidProtocol(){
return protocol == null;
}
@Override
public int getProtocolVersion(){
return protocol.getProtocol();
}
@Override
public int getOnlinePlayers(){
return builder.getOnlinePlayers();
}
@Override
public int getMaxPlayers(){
return builder.getMaximumPlayers();
}
@Override
public String getPlayerIP(){
return event.getConnection().getRemoteAddress().getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<Player> player){
return text;
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getConnection().getVirtualHost().orElse(null));
}
@Override
public PluginCore<Favicon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<Player> createPlayer(String name, int protocol){
return new VelocityPlayer(name, protocol);
}
@Override
public Favicon createFavicon(BufferedImage image){
return Favicon.create(image);
}
}