#1046 Add onFirstLogin to commands.yml

- Allow to configure commands run on player's first login (login of player with a previously null lastlogin date)
This commit is contained in:
ljacqu 2017-11-28 21:41:30 +01:00
parent 7932c1bf90
commit f1c1848985
10 changed files with 65 additions and 10 deletions

View File

@ -47,8 +47,8 @@ public class SyncProcessManager {
runTask(() -> processSyncPlayerLogout.processSyncLogout(player));
}
public void processSyncPlayerLogin(Player player) {
runTask(() -> processSyncPlayerLogin.processPlayerLogin(player));
public void processSyncPlayerLogin(Player player, boolean isFirstLogin) {
runTask(() -> processSyncPlayerLogin.processPlayerLogin(player, isFirstLogin));
}
public void processSyncPlayerQuit(Player player, boolean wasLoggedIn) {

View File

@ -220,6 +220,8 @@ public class AsynchronousLogin implements AsynchronousProcess {
*/
private void performLogin(Player player, PlayerAuth auth) {
if (player.isOnline()) {
final boolean isFirstLogin = (auth.getLastLogin() == null);
// Update auth to reflect this new login
final String ip = PlayerUtils.getPlayerIp(player);
auth.setRealName(player.getName());
@ -258,7 +260,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
// task, we schedule it in the end
// so that we can be sure, and have not to care if it might be
// processed in other order.
syncProcessManager.processSyncPlayerLogin(player);
syncProcessManager.processSyncPlayerLogin(player, isFirstLogin);
} else {
ConsoleLogger.warning("Player '" + player.getName() + "' wasn't online during login process, aborted...");
}

View File

@ -62,7 +62,13 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
}
}
public void processPlayerLogin(Player player) {
/**
* Performs operations in sync mode for a player that has just logged in.
*
* @param player the player that was logged in
* @param isFirstLogin true if this is the first time the player logged in
*/
public void processPlayerLogin(Player player, boolean isFirstLogin) {
final String name = player.getName().toLowerCase();
final LimboPlayer limbo = limboService.getLimboPlayer(name);
@ -93,6 +99,9 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
welcomeMessageConfiguration.sendWelcomeMessage(player);
// Login is now finished; we can force all commands
if (isFirstLogin) {
commandManager.runCommandsOnFirstLogin(player);
}
commandManager.runCommandsOnLogin(player);
// Send Bungee stuff. The service will check if it is enabled or not.

View File

@ -13,6 +13,7 @@ public class CommandConfig {
private Map<String, Command> onJoin = new LinkedHashMap<>();
private Map<String, Command> onLogin = new LinkedHashMap<>();
private Map<String, Command> onSessionLogin = new LinkedHashMap<>();
private Map<String, Command> onFirstLogin = new LinkedHashMap<>();
private Map<String, Command> onRegister = new LinkedHashMap<>();
private Map<String, Command> onUnregister = new LinkedHashMap<>();
private Map<String, Command> onLogout = new LinkedHashMap<>();
@ -41,6 +42,14 @@ public class CommandConfig {
this.onSessionLogin = onSessionLogin;
}
public Map<String, Command> getOnFirstLogin() {
return onFirstLogin;
}
public void setOnFirstLogin(Map<String, Command> onFirstLogin) {
this.onFirstLogin = onFirstLogin;
}
public Map<String, Command> getOnRegister() {
return onRegister;
}

View File

@ -34,6 +34,7 @@ public class CommandManager implements Reloadable {
private WrappedTagReplacer<Command, Player> onJoinCommands;
private WrappedTagReplacer<Command, Player> onLoginCommands;
private WrappedTagReplacer<Command, Player> onSessionLoginCommands;
private WrappedTagReplacer<Command, Player> onFirstLoginCommands;
private WrappedTagReplacer<Command, Player> onRegisterCommands;
private WrappedTagReplacer<Command, Player> onUnregisterCommands;
private WrappedTagReplacer<Command, Player> onLogoutCommands;
@ -75,7 +76,6 @@ public class CommandManager implements Reloadable {
executeCommands(player, onLoginCommands.getAdaptedItems(player));
}
/**
* Runs the configured commands for when a player has logged in successfully due to session.
*
@ -85,6 +85,15 @@ public class CommandManager implements Reloadable {
executeCommands(player, onSessionLoginCommands.getAdaptedItems(player));
}
/**
* Runs the configured commands for when a player logs in the first time.
*
* @param player the player that has logged in for the first time
*/
public void runCommandsOnFirstLogin(Player player) {
executeCommands(player, onFirstLoginCommands.getAdaptedItems(player));
}
/**
* Runs the configured commands for when a player has been unregistered.
*
@ -124,6 +133,7 @@ public class CommandManager implements Reloadable {
CommandConfig commandConfig = settingsManager.getProperty(CommandSettingsHolder.COMMANDS);
onJoinCommands = newReplacer(commandConfig.getOnJoin());
onLoginCommands = newReplacer(commandConfig.getOnLogin());
onFirstLoginCommands = newReplacer(commandConfig.getOnFirstLogin());
onSessionLoginCommands = newReplacer(commandConfig.getOnSessionLogin());
onRegisterCommands = newReplacer(commandConfig.getOnRegister());
onUnregisterCommands = newReplacer(commandConfig.getOnUnregister());

View File

@ -23,7 +23,7 @@ class CommandMigrationService implements MigrationService {
/** List of all properties in {@link CommandConfig}. */
@VisibleForTesting
static final List<String> COMMAND_CONFIG_PROPERTIES = ImmutableList.of(
"onJoin", "onLogin", "onSessionLogin", "onRegister", "onUnregister", "onLogout");
"onJoin", "onLogin", "onSessionLogin", "onFirstLogin", "onRegister", "onUnregister", "onLogout");
@Inject
private SettingsMigrationService settingsMigrationService;

View File

@ -22,7 +22,7 @@ public final class CommandSettingsHolder implements SettingsHolder {
@SectionComments
public static Map<String, String[]> sectionComments() {
String[] comments = {
String[] rootComments = {
"This configuration file allows you to execute commands on various events.",
"Supported placeholders in commands:",
" %p is replaced with the player name.",
@ -48,10 +48,14 @@ public final class CommandSettingsHolder implements SettingsHolder {
" command: 'broadcast %p has joined, welcome back!'",
" executor: CONSOLE",
"",
"Supported command events: onLogin, onSessionLogin, onJoin, onLogout, onRegister, onUnregister"
"Supported command events: onLogin, onSessionLogin, onFirstLogin, onJoin, onLogout, onRegister, "
+ "onUnregister"
};
Map<String, String[]> commentMap = new HashMap<>();
commentMap.put("", comments);
commentMap.put("", rootComments);
commentMap.put("onFirstLogin", new String[]{
"Commands to run for players logging in whose 'last login date' was empty"
});
commentMap.put("onUnregister", new String[]{
"Commands to run whenever a player is unregistered (by himself, or by an admin)"
});

View File

@ -24,7 +24,9 @@
# command: 'broadcast %p has joined, welcome back!'
# executor: CONSOLE
#
# Supported command events: onLogin, onSessionLogin, onJoin, onLogout, onRegister, onUnregister
# Supported command events: onLogin, onSessionLogin, onFirstLogin, onJoin, onLogout, onRegister, onUnregister
# Commands to run for players logging in whose 'last login date' was empty
onFirstLogin: {}
onJoin: {}
onLogin: {}
# These commands are called whenever a logged in player uses /logout or quits.

View File

@ -107,6 +107,21 @@ public class CommandManagerTest {
verifyZeroInteractions(geoIpService);
}
@Test
public void shouldExecuteCommandsOnFirstLogin() {
// given
copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.complete.yml");
initManager();
// when
manager.runCommandsOnFirstLogin(player);
// then
verify(bukkitService).dispatchConsoleCommand("pay Bobby 30");
verifyNoMoreInteractions(bukkitService);
verifyZeroInteractions(geoIpService);
}
@Test
public void shouldExecuteCommandsOnJoin() {
// given

View File

@ -25,6 +25,10 @@ onSessionLogin:
welcome:
command: 'msg %p Session login!'
executor: CONSOLE
onFirstLogin:
give_money:
command: 'pay %p 30'
executor: CONSOLE
onUnregister: {}
onLogout:
announce: