99
1010import java .util .Arrays ;
1111import java .util .Collection ;
12+ import java .util .Date ;
1213import java .util .HashSet ;
1314import java .util .List ;
15+ import java .util .Objects ;
1416import java .util .Set ;
1517import java .util .Stack ;
1618import java .util .regex .Pattern ;
1719
1820import com .dumptruckman .minecraft .util .Logging ;
21+ import org .bukkit .Bukkit ;
22+ import org .bukkit .command .CommandSender ;
1923import org .bukkit .configuration .ConfigurationSection ;
24+ import org .bukkit .entity .Entity ;
2025import org .jetbrains .annotations .ApiStatus ;
26+ import org .jetbrains .annotations .NotNull ;
2127import org .jetbrains .annotations .Nullable ;
28+ import org .mvplugins .multiverse .core .command .MVCommandManager ;
2229import org .mvplugins .multiverse .core .config .handle .MemoryConfigurationHandle ;
2330import org .mvplugins .multiverse .core .config .handle .StringPropertyHandle ;
2431import org .mvplugins .multiverse .core .config .migration .ConfigMigrator ;
2734import org .mvplugins .multiverse .core .destination .DestinationInstance ;
2835import org .mvplugins .multiverse .core .destination .DestinationsProvider ;
2936import org .mvplugins .multiverse .core .teleportation .BlockSafety ;
37+ import org .mvplugins .multiverse .core .utils .result .Attempt ;
38+ import org .mvplugins .multiverse .core .utils .text .ChatTextFormatter ;
3039import org .mvplugins .multiverse .core .world .LoadedMultiverseWorld ;
3140import org .mvplugins .multiverse .core .world .WorldManager ;
41+ import org .mvplugins .multiverse .external .vavr .control .Option ;
3242import org .mvplugins .multiverse .external .vavr .control .Try ;
43+ import org .mvplugins .multiverse .portals .action .ActionFailureReason ;
44+ import org .mvplugins .multiverse .portals .action .ActionHandler ;
45+ import org .mvplugins .multiverse .portals .action .ActionHandlerProvider ;
46+ import org .mvplugins .multiverse .portals .action .ActionHandlerType ;
3347import org .mvplugins .multiverse .portals .config .PortalsConfig ;
3448import org .mvplugins .multiverse .portals .enums .PortalType ;
3549import org .bukkit .Location ;
@@ -62,6 +76,8 @@ public static MVPortal loadMVPortalFromConfig(MultiversePortals instance, String
6276 private final WorldManager worldManager ;
6377 private final DestinationsProvider destinationsProvider ;
6478 private final BlockSafety blockSafety ;
79+ private final ActionHandlerProvider actionHandlerProvider ;
80+ private final MVCommandManager commandManager ;
6581
6682 private final String name ;
6783 private final MVPortalNodes configNodes ;
@@ -94,16 +110,24 @@ private MVPortal(MultiversePortals plugin, String name) {
94110 this .worldManager = this .plugin .getServiceLocator ().getService (WorldManager .class );
95111 this .destinationsProvider = this .plugin .getServiceLocator ().getService (DestinationsProvider .class );
96112 this .blockSafety = this .plugin .getServiceLocator ().getService (BlockSafety .class );
113+ this .actionHandlerProvider = this .plugin .getServiceLocator ().getService (ActionHandlerProvider .class );
114+ this .commandManager = this .plugin .getServiceLocator ().getService (MVCommandManager .class );
97115
98116 this .name = name ;
99117
100118 var config = this .plugin .getPortalsConfig ();
101119 this .configNodes = new MVPortalNodes (plugin , this );
102- var portalSection = config .getConfigurationSection ("portals." + this .name );
103- if (portalSection == null ) {
104- portalSection = config .createSection ("portals." + this .name );
105- }
106- this .configHandle = MemoryConfigurationHandle .builder (portalSection , configNodes .getNodes ())
120+ var portalSection = Option .of (config .getConfigurationSection ("portals." + this .name ))
121+ .getOrElse (() -> config .createSection ("portals." + this .name ));
122+ this .configHandle = setUpConfigHandle (portalSection );
123+ this .stringPropertyHandle = new StringPropertyHandle (this .configHandle );
124+ configHandle .load ();
125+
126+ setUpPermissions ();
127+ }
128+
129+ private MemoryConfigurationHandle setUpConfigHandle (ConfigurationSection portalSection ) {
130+ return MemoryConfigurationHandle .builder (portalSection , configNodes .getNodes ())
107131 .migrator (ConfigMigrator .builder (configNodes .version )
108132 .addVersionMigrator (VersionMigrator .builder (1.0 )
109133 .addAction (MoveMigratorAction .of ("safeteleport" , "safe-teleport" ))
@@ -119,11 +143,14 @@ private MVPortal(MultiversePortals plugin, String name) {
119143 }
120144 })
121145 .build ())
146+ .addVersionMigrator (VersionMigrator .builder (1.2 )
147+ .addAction (MoveMigratorAction .of ("destination" , "action" ))
148+ .build ())
122149 .build ())
123150 .build ();
124- this .stringPropertyHandle = new StringPropertyHandle (this .configHandle );
125- configHandle .load ();
151+ }
126152
153+ private void setUpPermissions () {
127154 this .permission = this .plugin .getServer ().getPluginManager ().getPermission ("multiverse.portal.access." + this .name );
128155 if (this .permission == null ) {
129156 this .permission = new Permission ("multiverse.portal.access." + this .name , "Allows access to the " + this .name + " portal" , PermissionDefault .OP );
@@ -142,6 +169,10 @@ private MVPortal(MultiversePortals plugin, String name) {
142169 }
143170 }
144171
172+ /**
173+ *
174+ * @return
175+ */
145176 public String getName () {
146177 return this .name ;
147178 }
@@ -271,24 +302,61 @@ public PortalLocation getPortalLocation() {
271302 return this .location ;
272303 }
273304
274- public boolean setDestination (String destinationString ) {
275- DestinationInstance <?, ?> newDestination = this .destinationsProvider .parseDestination (destinationString ).getOrNull ();
276- return setDestination (newDestination );
305+ @ ApiStatus .AvailableSince ("5.2" )
306+ public Try <Void > setActionType (@ NotNull ActionHandlerType <?, ?> actionType ) {
307+ Objects .requireNonNull (actionType , "actionType cannot be null" );
308+ return configHandle .set (configNodes .actionType , actionType .getName ());
277309 }
278310
279- public boolean setDestination (DestinationInstance <?, ?> newDestination ) {
280- if (newDestination == null ) {
281- Logging .warning ("Portal " + this .name + " has an invalid DESTINATION!" );
282- return false ;
283- }
284- return this .configHandle .set (configNodes .destination , newDestination .toString ()).isSuccess ();
311+ @ ApiStatus .AvailableSince ("5.2" )
312+ public Try <Void > setActionType (String actionType ) {
313+ return configHandle .set (configNodes .actionType , actionType );
285314 }
286315
287- public DestinationInstance <?, ?> getDestination () {
288- return this .destinationsProvider .parseDestination (this .configHandle .get (configNodes .destination ))
289- .onFailure (f ->
290- Logging .warning ("Portal " + this .name + " has an invalid DESTINATION! " + f .getFailureMessage ().formatted ()))
291- .getOrNull ();
316+ @ ApiStatus .AvailableSince ("5.2" )
317+ public String getActionType () {
318+ return this .configHandle .get (configNodes .actionType );
319+ }
320+
321+ @ ApiStatus .AvailableSince ("5.2" )
322+ public Try <Void > setAction (String action ) {
323+ return configHandle .set (configNodes .action , action );
324+ }
325+
326+ @ ApiStatus .AvailableSince ("5.2" )
327+ public String getAction () {
328+ return configHandle .get (configNodes .action );
329+ }
330+
331+ @ ApiStatus .AvailableSince ("5.2" )
332+ public Try <Void > setActionHandler (@ NotNull ActionHandler <?, ?> action ) {
333+ Objects .requireNonNull (action , "action cannot be null" );
334+ return setActionType (action .getHandlerType ())
335+ .flatMap (v -> setAction (action .serialise ()));
336+ }
337+
338+ @ ApiStatus .AvailableSince ("5.2" )
339+ public @ NotNull Attempt <? extends ActionHandler <?, ?>, ActionFailureReason > getActionHandler () {
340+ return actionHandlerProvider .parseHandler (getActionType (), getAction ());
341+ }
342+
343+ @ ApiStatus .AvailableSince ("5.2" )
344+ public @ NotNull Attempt <? extends ActionHandler <?, ?>, ActionFailureReason > getActionHandler (@ NotNull CommandSender sender ) {
345+ return actionHandlerProvider .parseHandler (sender , getActionType (), getAction ());
346+ }
347+
348+ @ ApiStatus .AvailableSince ("5.2" )
349+ public @ NotNull Attempt <Void , ActionFailureReason > runActionFor (Entity entity ) {
350+ return getActionHandler (entity )
351+ .mapAttempt (actionHandler -> actionHandler .runAction (this , entity ))
352+ .onSuccess (() -> {
353+ if (entity instanceof Player player ) {
354+ plugin .getPortalSession (player ).setTeleportTime (new Date ());
355+ }
356+ })
357+ .onFailure (failure ->
358+ Logging .warning (ChatTextFormatter .removeColor ("Invalid Portal Action: " +
359+ failure .getFailureMessage ().formatted (commandManager .getCommandIssuer (Bukkit .getConsoleSender ())))));
292360 }
293361
294362 /**
@@ -598,4 +666,54 @@ public boolean isExempt(Player player) {
598666 public PortalLocation getLocation () {
599667 return getPortalLocation ();
600668 }
669+
670+ /**
671+ * @deprecated Portals now have new types of action. Hence, the portal's destination (now called action) may not
672+ * always be a multiverse destination. It can be a command or server name as well.
673+ * Please see {@link MVPortal#getActionHandler()} instead.
674+ */
675+ @ Deprecated (since = "5.2" , forRemoval = true )
676+ @ ApiStatus .ScheduledForRemoval (inVersion = "6.0" )
677+ public boolean setDestination (String destinationString ) {
678+ DestinationInstance <?, ?> newDestination = this .destinationsProvider .parseDestination (destinationString ).getOrNull ();
679+ return setDestination (newDestination );
680+ }
681+
682+ /**
683+ * @deprecated Portals now have new types of action. Hence, the portal's destination (now called action) may not
684+ * always be a multiverse destination. For example, it can be a command or server name as well.
685+ * Please see {@link MVPortal#getActionHandler()} instead.
686+ */
687+ @ Deprecated (since = "5.2" , forRemoval = true )
688+ @ ApiStatus .ScheduledForRemoval (inVersion = "6.0" )
689+ public boolean setDestination (DestinationInstance <?, ?> newDestination ) {
690+ if (newDestination == null ) {
691+ Logging .warning ("Portal " + this .name + " has an invalid DESTINATION!" );
692+ return false ;
693+ }
694+ if (!Objects .equals (getActionType (), "multiverse-destination" )) {
695+ Logging .warning ("Portal " + this .name + " is not set to use multiverse destination!" );
696+ return false ;
697+ }
698+ return setActionType ("multiverse-destination" )
699+ .flatMap (ignore -> setAction (newDestination .toString ()))
700+ .isSuccess ();
701+ }
702+
703+ /**
704+ * @deprecated Portals now have new types of action. Hence, the portal's destination (now called action) may not
705+ * always be a multiverse destination. For example, it can be a command or server name as well.
706+ * Please see {@link MVPortal#getActionHandler()} instead.
707+ */
708+ @ Deprecated (since = "5.2" , forRemoval = true )
709+ @ ApiStatus .ScheduledForRemoval (inVersion = "6.0" )
710+ public @ Nullable DestinationInstance <?, ?> getDestination () {
711+ return this .destinationsProvider .parseDestination (getAction ())
712+ .onFailure (f -> {
713+ if (getAction ().equals ("multiverse-destination" )) {
714+ Logging .warning ("Portal " + this .name + " has an invalid DESTINATION! " + f .getFailureMessage ().formatted ());
715+ }
716+ })
717+ .getOrNull ();
718+ }
601719}
0 commit comments