Skip to content

Commit

Permalink
Snapshot 2.1.0 (#27)
Browse files Browse the repository at this point in the history
* Fix code style inconsistencies

* Improve dispatching flow and internal encapsulation

* Add delegating placeholder sanitizer

* Add more efficient implementation for placeholder sanitizer for adventure

* Decomposition of functions, support dry kiss principles / noyzys
  • Loading branch information
rchomczyk authored Nov 19, 2024
1 parent c040f9b commit 7483a17
Show file tree
Hide file tree
Showing 47 changed files with 586 additions and 479 deletions.
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,21 @@ hasle on developer side.

```java
AdventureMessageDispatcher.createTitle()
.recipient(event.getPlayer())
.viewer(event.getPlayer())
.title(it -> it.template(formatter, "Hello!"))
.subtitle(it -> it.template(formatter, "It is a pleasure to see you there {{player.getName}}"))
.variable("player", event.getPlayer())
.times(2, 4, 2)
.dispatch();

AdventureMessageDispatcher.createChat()
.recipient(Bukkit.getServer())
.viewer(Bukkit.getServer())
.template(formatter, "{{player.getName}} has joined the server!")
.variable("player", event.getPlayer())
.dispatch();

AdventureMessageDispatcher.createActionBar()
.recipient(event.getPlayer())
.viewer(event.getPlayer())
.template(formatter, "Honey is great, isn't it?")
.dispatch();
```
Expand All @@ -88,25 +88,25 @@ AdventureMessageDispatcher.createActionBar()

```java
AdventureMessageDispatcher.createChat()
.recipient(Bukkit.getServer())
.viewer(Bukkit.getServer())
.template(Component.text("Somebody joined to the server!").color(NamedTextColor.RED))
.dispatch();

AdventureMessageDispatcher.createActionBar()
.recipient(event.getPlayer())
.viewer(event.getPlayer())
.template(Component.text("Honey is great, isn't it?"))
.dispatch();
```

### Use case (honey-kt-extesion)
```kotlin
AdventureMessageDispatcher.createChat()
.recipient(event.player)
.viewer(event.player)
.template(Component.text("Hello!"))
.dispatch()

AdventureMessageDispatcher.createActionBar()
.recipient(event.player)
.viewer(event.player)
.template(Component.text("This is an action bar message!"))
.dispatch()

Expand All @@ -119,7 +119,7 @@ player.createActionBar()
.dispatch()

AdventureMessageDispatcher.createTitle()
.recipient(event.player)
.viewer(event.player)
.title { it.template(Component.text("Hello!")) }
.subtitle { it.template(Component.text("It's great to see you!")) }
.times(2, 4, 2)
Expand All @@ -128,7 +128,7 @@ AdventureMessageDispatcher.createTitle()

### Synchronous vs asynchronous message dispatching
- [dispatch](https://github.com/rchomczyk/honey/tree/main/honey-common/src/dev/shiza/honey/message/dispatcher/MessageBaseDispatcher.java#L71)
This method immediately delivers the message synchronously. It calls the deliver function with the rendered message and the recipient, and the action is completed immediately.
This method immediately delivers the message synchronously. It calls the deliver function with the rendered message and the viewer, and the action is completed immediately.

- [dispatchAsync](https://github.com/rchomczyk/honey/tree/main/honey-common/src/dev/shiza/honey/message/dispatcher/MessageBaseDispatcher.java#L76)
This method delivers the message asynchronously. It returns a CompletableFuture that performs the message rendering in the background and then delivers the result once it's ready. It allows non-blocking behavior and handles exceptions asynchronously.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/honey-publish.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group = "dev.shiza"
version = "2.0.3-SNAPSHOT"
version = "2.1.0-SNAPSHOT"

java {
withSourcesJar()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import dev.shiza.honey.adventure.placeholder.ParsableValue;
import dev.shiza.honey.message.compiler.MessageCompiler;
import dev.shiza.honey.placeholder.sanitizer.SanitizedPlaceholder;
import dev.shiza.honey.placeholder.sanitizer.PlaceholderSanitizer.SanitizedPlaceholder;
import java.util.List;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
Expand Down Expand Up @@ -46,12 +46,9 @@ public Component compile(
* @return An array of {@link TagResolver}.
*/
private TagResolver[] getPlaceholderTags(final List<SanitizedPlaceholder> placeholders) {
final TagResolver[] tagResolvers = new TagResolver[placeholders.size()];
for (int index = 0; index < tagResolvers.length; index++) {
final SanitizedPlaceholder placeholder = placeholders.get(index);
tagResolvers[index] = getPlaceholderTags(placeholder.key(), placeholder.evaluatedValue());
}
return tagResolvers;
return placeholders.stream()
.map(placeholder -> getPlaceholderTags(placeholder.key(), placeholder.evaluatedValue()))
.toArray(TagResolver[]::new);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.spotify.futures.CompletableFutures;
import dev.shiza.honey.message.dispatcher.MessageBaseDispatcher;
import dev.shiza.honey.message.dispatcher.MessageDispatcher;
import dev.shiza.honey.message.dispatcher.MessageRenderer;
import dev.shiza.honey.message.dispatcher.TitleMessageDispatcher;
import java.time.Duration;
import java.util.List;
Expand All @@ -18,39 +19,39 @@
/**
* This class is responsible for dispatching title messages to an audience in the Adventure
* framework. It manages separate dispatchers for times, title, and subtitle, as well as keeping
* track of the recipient.
* track of the viewer.
*/
public final class AdventureTitleMessageDispatcher
implements TitleMessageDispatcher<Audience, Component> {

private final MessageDispatcher<Audience, Component> times;
private final MessageDispatcher<Audience, Component> title;
private final MessageDispatcher<Audience, Component> subtitle;
private final Audience recipient;
private final Audience viewer;

/**
* Constructs a new AdventureTitleMessageDispatcher with specified dispatchers for times, title,
* subtitle and a recipient.
* subtitle and a viewer.
*
* @param times the dispatcher for handling the timing of title messages
* @param title the dispatcher for handling the main title messages
* @param subtitle the dispatcher for handling the subtitle messages
* @param recipient the audience that will receive the title messages
* @param viewer the audience that will receive the title messages
*/
public AdventureTitleMessageDispatcher(
final MessageDispatcher<Audience, Component> times,
final MessageDispatcher<Audience, Component> title,
final MessageDispatcher<Audience, Component> subtitle,
final Audience recipient) {
final Audience viewer) {
this.times = times;
this.title = title;
this.subtitle = subtitle;
this.recipient = recipient;
this.viewer = viewer;
}

/**
* Default constructor that initializes with default dispatchers for times, title, and subtitle,
* with an empty recipient.
* with an empty viewer.
*/
public AdventureTitleMessageDispatcher() {
this(
Expand Down Expand Up @@ -82,9 +83,9 @@ public TitleMessageDispatcher<Audience, Component> times(
Duration.ofSeconds(fadeIn), Duration.ofSeconds(stay), Duration.ofSeconds(fadeOut));
final MessageDispatcher<Audience, Component> timesDispatcher =
new MessageBaseDispatcher<>(
recipient, (audience, component) -> audience.sendTitlePart(TitlePart.TIMES, titleTime));
viewer, (audience, component) -> audience.sendTitlePart(TitlePart.TIMES, titleTime));
return new AdventureTitleMessageDispatcher(
timesDispatcher.template(Component.empty()), title, subtitle, recipient);
timesDispatcher.template(Component.empty()), title, subtitle, viewer);
}

/**
Expand All @@ -96,7 +97,7 @@ public TitleMessageDispatcher<Audience, Component> times(
@Override
public TitleMessageDispatcher<Audience, Component> title(
final UnaryOperator<MessageDispatcher<Audience, Component>> consumer) {
return new AdventureTitleMessageDispatcher(times, consumer.apply(title), subtitle, recipient);
return new AdventureTitleMessageDispatcher(times, consumer.apply(title), subtitle, viewer);
}

/**
Expand All @@ -108,30 +109,40 @@ public TitleMessageDispatcher<Audience, Component> title(
@Override
public TitleMessageDispatcher<Audience, Component> subtitle(
final UnaryOperator<MessageDispatcher<Audience, Component>> consumer) {
return new AdventureTitleMessageDispatcher(times, title, consumer.apply(subtitle), recipient);
return new AdventureTitleMessageDispatcher(times, title, consumer.apply(subtitle), viewer);
}

@Override
public TitleMessageDispatcher<Audience, Component> placeholders(
final UnaryOperator<MessageRenderer<Component>> consumer) {
return new AdventureTitleMessageDispatcher(
times.placeholders(consumer),
title.placeholders(consumer),
subtitle.placeholders(consumer),
viewer);
}

/**
* Updates the recipient of title messages.
* Updates the viewer of title messages.
*
* @param recipient the new recipient for the title messages
* @return a new instance of AdventureTitleMessageDispatcher with the updated recipient
* @param viewer the new viewer for the title messages
* @return a new instance of AdventureTitleMessageDispatcher with the updated viewer
*/
@Override
public TitleMessageDispatcher<Audience, Component> recipient(final Audience recipient) {
return new AdventureTitleMessageDispatcher(times, title, subtitle, recipient);
public TitleMessageDispatcher<Audience, Component> viewer(final Audience viewer) {
return new AdventureTitleMessageDispatcher(times, title, subtitle, viewer);
}

/** Dispatches the title, subtitle, and timing messages to the recipient synchronously. */
/** Dispatches the title, subtitle, and timing messages to the viewer synchronously. */
@Override
public void dispatch() {
times.recipient(recipient).dispatch();
title.recipient(recipient).dispatch();
subtitle.recipient(recipient).dispatch();
times.viewer(viewer).dispatch();
title.viewer(viewer).dispatch();
subtitle.viewer(viewer).dispatch();
}

/**
* Dispatches the title, subtitle, and timing messages to the recipient asynchronously.
* Dispatches the title, subtitle, and timing messages to the viewer asynchronously.
*
* @return a CompletableFuture representing pending completion of the task, with a list of Void,
* indicating when all dispatches are complete
Expand All @@ -140,8 +151,8 @@ public void dispatch() {
public CompletableFuture<List<Void>> dispatchAsync() {
return CompletableFutures.allAsList(
ImmutableList.of(
times.recipient(recipient).dispatchAsync(),
title.recipient(recipient).dispatchAsync(),
subtitle.recipient(recipient).dispatchAsync()));
times.viewer(viewer).dispatchAsync(),
title.viewer(viewer).dispatchAsync(),
subtitle.viewer(viewer).dispatchAsync()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.shiza.honey.message.compiler.MessageCompiler;
import dev.shiza.honey.message.formatter.MessageBaseFormatter;
import dev.shiza.honey.placeholder.evaluator.PlaceholderContext;
import dev.shiza.honey.placeholder.PlaceholderContext;
import dev.shiza.honey.placeholder.processor.PlaceholderProcessor;
import dev.shiza.honey.placeholder.resolver.PlaceholderResolver;
import dev.shiza.honey.placeholder.sanitizer.PlaceholderSanitizer;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package dev.shiza.honey.adventure.message.formatter;

import dev.shiza.honey.adventure.message.compiler.AdventureMessageCompilerFactory;
import dev.shiza.honey.adventure.placeholder.sanitizer.AdventurePlaceholderSanitizerFactory;
import dev.shiza.honey.conversion.ImplicitConversion;
import dev.shiza.honey.message.compiler.MessageCompiler;
import dev.shiza.honey.placeholder.evaluator.PlaceholderContext;
import dev.shiza.honey.placeholder.PlaceholderContext;
import dev.shiza.honey.placeholder.evaluator.PlaceholderEvaluator;
import dev.shiza.honey.placeholder.evaluator.reflection.ReflectivePlaceholderEvaluatorFactory;
import dev.shiza.honey.placeholder.processor.PlaceholderProcessor;
import dev.shiza.honey.placeholder.processor.PlaceholderProcessorFactory;
import dev.shiza.honey.placeholder.resolver.PlaceholderResolver;
import dev.shiza.honey.placeholder.resolver.PlaceholderResolverFactory;
import dev.shiza.honey.placeholder.sanitizer.PlaceholderSanitizer;
import dev.shiza.honey.placeholder.sanitizer.PlaceholderSanitizerFactory;
import dev.shiza.honey.processor.ProcessorRegistry;
import dev.shiza.honey.processor.ProcessorRegistryFactory;
import net.kyori.adventure.text.Component;
Expand Down Expand Up @@ -62,7 +62,7 @@ public static AdventureMessageFormatter create() {
final ImplicitConversion implicitConversion = ImplicitConversion.create();
final PlaceholderContext placeholderContext = PlaceholderContext.create();
final PlaceholderResolver placeholderResolver = PlaceholderResolverFactory.create();
final PlaceholderSanitizer placeholderSanitizer = PlaceholderSanitizerFactory.create();
final PlaceholderSanitizer placeholderSanitizer = AdventurePlaceholderSanitizerFactory.create();
final PlaceholderEvaluator placeholderEvaluator =
ReflectivePlaceholderEvaluatorFactory.create();
final PlaceholderProcessor placeholderProcessor =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package dev.shiza.honey.adventure.placeholder.sanitizer;

import dev.shiza.honey.placeholder.evaluator.PlaceholderEvaluator.EvaluatedPlaceholder;
import dev.shiza.honey.placeholder.sanitizer.PlaceholderSanitizer;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* This class is responsible for placeholder sanitization, which is the process of transforming
* placeholder key from honey's format to match the MiniMessage's format.
*/
final class AdventurePlaceholderSanitizer implements PlaceholderSanitizer {

private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{\\{(.*?)}}");
private static final String MINI_MESSAGE_PLACEHOLDER_FORMAT = "<%s>";

AdventurePlaceholderSanitizer() {}

@Override
public String getSanitizedContent(
final String content, final List<SanitizedPlaceholder> placeholders) {
return processPlaceholders(content, MINI_MESSAGE_PLACEHOLDER_FORMAT);
}

@Override
public SanitizedPlaceholder getSanitizedPlaceholder(final EvaluatedPlaceholder placeholder) {
final String sanitized = processPlaceholders(placeholder.placeholder().key(), "%s");
return new SanitizedPlaceholder(
sanitized, placeholder.placeholder().key(), placeholder.evaluatedValue());
}

private String processPlaceholders(final String input, final String format) {
final Matcher matcher = PLACEHOLDER_PATTERN.matcher(input);
final StringBuilder result = new StringBuilder();
while (matcher.find()) {
matcher.appendReplacement(result, format.formatted(matcher.group(1)));
}
matcher.appendTail(result);
return result.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.shiza.honey.adventure.placeholder.sanitizer;

import dev.shiza.honey.placeholder.sanitizer.PlaceholderSanitizer;

public final class AdventurePlaceholderSanitizerFactory {

private AdventurePlaceholderSanitizerFactory() {}

public static PlaceholderSanitizer create() {
return new AdventurePlaceholderSanitizer();
}

public static PlaceholderSanitizer createReflective() {
return new AdventureReflectivePlaceholderSanitizer();
}
}
Loading

0 comments on commit 7483a17

Please sign in to comment.