Files
fabric-carpet/src/main/java/carpet/logging/Logger.java
T
2020-04-15 02:12:57 -03:00

235 lines
7.3 KiB
Java

package carpet.logging;
import carpet.CarpetServer;
import carpet.CarpetSettings;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.BaseText;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
public class Logger
{
// The set of subscribed and online players.
private Map<String, String> subscribedOnlinePlayers;
// The set of subscribed and offline players.
private Map<String,String> subscribedOfflinePlayers;
// The logName of this log. Gets prepended to logged messages.
private String logName;
private String default_option;
private String[] options;
private Field acceleratorField;
static Logger stardardLogger(String logName, String def, String [] options)
{
try
{
return new Logger(LoggerRegistry.class.getField("__"+logName), logName, def, options);
}
catch (NoSuchFieldException e)
{
throw new RuntimeException("Failed to create logger "+logName);
}
}
public Logger(Field acceleratorField, String logName, String def, String [] options)
{
subscribedOnlinePlayers = new HashMap<>();
subscribedOfflinePlayers = new HashMap<>();
this.acceleratorField = acceleratorField;
this.logName = logName;
this.default_option = def;
this.options = options;
if (acceleratorField == null)
CarpetSettings.LOG.error("[CM] Logger "+getLogName()+" is missing a specified accelerator");
}
public String getDefault()
{
return default_option;
}
public String [] getOptions()
{
if (options == null)
{
return new String[0];
}
return options;
}
public String getLogName()
{
return logName;
}
/**
* Subscribes the player with the given logName to the logger.
*/
public void addPlayer(String playerName, String option)
{
if (playerFromName(playerName) != null)
{
subscribedOnlinePlayers.put(playerName, option);
}
else
{
subscribedOfflinePlayers.put(playerName, option);
}
LoggerRegistry.setAccess(this);
}
/**
* Unsubscribes the player with the given logName from the logger.
*/
public void removePlayer(String playerName)
{
subscribedOnlinePlayers.remove(playerName);
subscribedOfflinePlayers.remove(playerName);
LoggerRegistry.setAccess(this);
}
/**
* Returns true if there are any online subscribers for this log.
*/
public boolean hasOnlineSubscribers()
{
return subscribedOnlinePlayers.size() > 0;
}
public void serverStopped()
{
subscribedOnlinePlayers.clear();
subscribedOfflinePlayers.clear();
}
public Field getField()
{
return acceleratorField;
}
/**
* serves messages to players fetching them from the promise
* will repeat invocation for players that share the same option
*/
@FunctionalInterface
public interface lMessage { BaseText [] get(String playerOption, PlayerEntity player);}
public void log(lMessage messagePromise)
{
for (Map.Entry<String,String> en : subscribedOnlinePlayers.entrySet())
{
ServerPlayerEntity player = playerFromName(en.getKey());
if (player != null)
{
BaseText [] messages = messagePromise.get(en.getValue(),player);
if (messages != null)
sendPlayerMessage(player, messages);
}
}
}
/**
* guarantees that each message for each option will be evaluated once from the promise
* and served the same way to all other players subscribed to the same option
*/
@FunctionalInterface
public interface lMessageIgnorePlayer { BaseText [] get(String playerOption);}
public void log(lMessageIgnorePlayer messagePromise)
{
Map<String, BaseText[]> cannedMessages = new HashMap<>();
for (Map.Entry<String,String> en : subscribedOnlinePlayers.entrySet())
{
ServerPlayerEntity player = playerFromName(en.getKey());
if (player != null)
{
String option = en.getValue();
if (!cannedMessages.containsKey(option))
{
cannedMessages.put(option,messagePromise.get(option));
}
BaseText [] messages = cannedMessages.get(option);
if (messages != null)
sendPlayerMessage(player, messages);
}
}
}
/**
* guarantees that message is evaluated once, so independent from the player and chosen option
*/
public void log(Supplier<BaseText[]> messagePromise)
{
BaseText [] cannedMessages = null;
for (Map.Entry<String,String> en : subscribedOnlinePlayers.entrySet())
{
ServerPlayerEntity player = playerFromName(en.getKey());
if (player != null)
{
if (cannedMessages == null) cannedMessages = messagePromise.get();
sendPlayerMessage(player, cannedMessages);
}
}
}
public void sendPlayerMessage(ServerPlayerEntity player, BaseText ... messages)
{
Arrays.stream(messages).forEach(player::sendSystemMessage);
}
/**
* Gets the {@code PlayerEntity} instance for a player given their UUID. Returns null if they are offline.
*/
protected ServerPlayerEntity playerFromName(String name)
{
return CarpetServer.minecraft_server.getPlayerManager().getPlayer(name);
}
// ----- Event Handlers ----- //
public void onPlayerConnect(PlayerEntity player, boolean firstTime)
{
// If the player was subscribed to the log and offline, move them to the set of online subscribers.
String playerName = player.getName().getString();
if (subscribedOfflinePlayers.containsKey(playerName))
{
subscribedOnlinePlayers.put(playerName, subscribedOfflinePlayers.get(playerName));
subscribedOfflinePlayers.remove(playerName);
}
else if(firstTime)
{
Set<String> loggingOptions = new HashSet<>(Arrays.asList(CarpetSettings.defaultLoggers.split(",")));
if (loggingOptions.contains(getLogName()))
{
LoggerRegistry.subscribePlayer(playerName, getLogName(), getDefault());
}
}
LoggerRegistry.setAccess(this);
}
public void onPlayerDisconnect(PlayerEntity player)
{
// If the player was subscribed to the log, move them to the set of offline subscribers.
String playerName = player.getName().getString();
if (subscribedOnlinePlayers.containsKey(playerName))
{
subscribedOfflinePlayers.put(playerName, subscribedOnlinePlayers.get(playerName));
subscribedOnlinePlayers.remove(playerName);
}
LoggerRegistry.setAccess(this);
}
public String getAcceptedOption(String arg)
{
if (options != null && Arrays.asList(options).contains(arg)) return arg;
return null;
}
}