Skip to content

Commit

Permalink
Properly encapsulate adventure implementation as separate module
Browse files Browse the repository at this point in the history
  • Loading branch information
rchomczyk committed Mar 5, 2025
1 parent e86c911 commit 279e85c
Show file tree
Hide file tree
Showing 109 changed files with 2,517 additions and 2,537 deletions.
6 changes: 4 additions & 2 deletions .idea/gradle.xml

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

6 changes: 6 additions & 0 deletions .idea/palantir-java-format.xml

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

43 changes: 2 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,8 @@ A message library, which focuses on simplicity and flexibility.
*honey* was created to allow for developers to create easily customizable messages for end users, by giving them flexibility with placeholders.

### Get started

#### Gradle DSL (kts) || std

##### Add repository

```kotlin
maven("https://repo.shiza.dev/releases")
```

```groovy
maven { url 'https://repo.shiza.dev/releases' }
```

##### Add dependency

```kotlin
implementation("dev.shiza:honey:2.2.2")
```

```groovy
implementation 'dev.shiza:honey:2.2.2'
```

#### Maven

##### Add repository
```xml
<repository>
<id>shiza-releases</id>
<url>https://repo.shiza.dev/releases</url>
</repository>
```

##### Add dependency
```xml
<dependency>
<groupId>dev.shiza</groupId>
<artifactId>honey</artifactId>
<version>2.2.2</version>
</dependency>
```
You can build dependency and append it to your local .m2 directory, by using:
`./gradlew publishToMavenLocal`

![test-plugin showcase](assets/image.png)

Expand Down
15 changes: 15 additions & 0 deletions honey-adventure/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
plugins {
`honey-java`
`honey-unit-test`
`honey-publish`
`honey-repositories`
}

dependencies {
api(project(":honey-common"))
api(libs.bundles.adventure)
}

honeyPublish {
artifactId = "honey-adventure"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package dev.shiza.honey.adventure.message.compiler;

import dev.shiza.honey.adventure.placeholder.ParsableValue;
import dev.shiza.honey.message.compiler.MessageCompiler;
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;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.intellij.lang.annotations.Subst;

import static net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component;
import static net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed;
import static net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.unparsed;

/**
* This class provides a mechanism to compile messages using the Adventure API MiniMessage format.
* It translates sanitized content and placeholders into formatted Adventure {@link Component}s.
*/
final class AdventureMessageCompiler implements MessageCompiler<Component> {

private final MiniMessage miniMessage;

AdventureMessageCompiler(final MiniMessage miniMessage) {
this.miniMessage = miniMessage;
}

/**
* Compiles the sanitized content and placeholders into an Adventure {@link Component}.
*
* @param sanitizedContent The sanitized content string to be compiled.
* @param placeholders The list of sanitized placeholders to be included in the content.
* @return The compiled message as an Adventure {@link Component}.
*/
@Override
public Component compile(
final String sanitizedContent, final List<SanitizedPlaceholder> placeholders) {
final TagResolver[] placeholderTags = getPlaceholderTags(placeholders);
return miniMessage.deserialize(sanitizedContent, placeholderTags);
}

/**
* Converts a list of {@link SanitizedPlaceholder} into an array of {@link TagResolver}.
*
* @param placeholders The list of placeholders to be converted.
* @return An array of {@link TagResolver}.
*/
private TagResolver[] getPlaceholderTags(final List<SanitizedPlaceholder> placeholders) {
return placeholders.stream()
.map(placeholder -> getPlaceholderTags(placeholder.key(), placeholder.evaluatedValue()))
.toArray(TagResolver[]::new);
}

/**
* Creates a {@link TagResolver} based on the key and the evaluated value of the placeholder. The
* method handles different types of evaluated values by converting them into suitable tag
* resolutions.
*
* @param key The key associated with the placeholder.
* @param evaluatedValue The evaluated value of the placeholder.
* @return The appropriate {@link TagResolver} based on the type of evaluated value.
*/
private TagResolver getPlaceholderTags(
final @Subst("default") String key, final Object evaluatedValue) {
if (evaluatedValue instanceof Component component) {
return component(key, component);
}

if (evaluatedValue instanceof ParsableValue parsableValue) {
return parsed(key, parsableValue.value());
}

return unparsed(key, evaluatedValue.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package dev.shiza.honey.adventure.message.compiler;

import dev.shiza.honey.message.compiler.MessageCompiler;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;

import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;

/**
* Factory for creating Adventure message compilers.
*/
public final class AdventureMessageCompilerFactory {

private AdventureMessageCompilerFactory() {}

/**
* Creates a message compiler using a specific MiniMessage.
*
* @param miniMessage the MiniMessage instance to use for the compiler.
* @return a new instance of {@link MessageCompiler<Component>} configured with the given
* MiniMessage.
*/
public static MessageCompiler<Component> create(final MiniMessage miniMessage) {
return new AdventureMessageCompiler(miniMessage);
}

/**
* Creates a default message compiler with default MiniMessage configuration.
*
* @return a new instance of {@link MessageCompiler<Component>} with the default MiniMessage
* configuration.
*/
public static MessageCompiler<Component> create() {
return new AdventureMessageCompiler(miniMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package dev.shiza.honey.adventure.message.dispatcher;

import com.google.common.collect.ImmutableList;
import com.spotify.futures.CompletableFutures;
import dev.shiza.honey.message.dispatcher.BatchMessageDispatcher;
import dev.shiza.honey.message.dispatcher.MessagePolyDispatcher;
import dev.shiza.honey.message.dispatcher.MessageRenderer;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.UnaryOperator;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;

public final class AdventureBatchMessageDispatcher
implements BatchMessageDispatcher<Audience, Component> {

private final List<MessagePolyDispatcher<Audience, Component>> dispatchers;

public AdventureBatchMessageDispatcher(
final List<MessagePolyDispatcher<Audience, Component>> dispatchers) {
this.dispatchers = ImmutableList.copyOf(dispatchers);
}

public AdventureBatchMessageDispatcher() {
this(ImmutableList.of());
}

@Override
public BatchMessageDispatcher<Audience, Component> add(
final MessagePolyDispatcher<Audience, Component> dispatcher) {
return new AdventureBatchMessageDispatcher(
ImmutableList.<MessagePolyDispatcher<Audience, Component>>builder()
.addAll(dispatchers)
.add(dispatcher)
.build());
}

@SafeVarargs
@Override
public final BatchMessageDispatcher<Audience, Component> addAll(
final MessagePolyDispatcher<Audience, Component>... dispatchers) {
return new AdventureBatchMessageDispatcher(
ImmutableList.<MessagePolyDispatcher<Audience, Component>>builder()
.addAll(this.dispatchers)
.addAll(Arrays.asList(dispatchers))
.build());
}

@Override
public MessagePolyDispatcher<Audience, Component> viewer(final Audience audience) {
return new AdventureBatchMessageDispatcher(
dispatchers.stream()
.map(dispatcher -> dispatcher.viewer(audience))
.collect(ImmutableList.toImmutableList()));
}

@Override
public MessagePolyDispatcher<Audience, Component> placeholders(
final UnaryOperator<MessageRenderer<Component>> consumer) {
return new AdventureBatchMessageDispatcher(
dispatchers.stream()
.map(dispatcher -> dispatcher.placeholders(consumer))
.collect(ImmutableList.toImmutableList()));
}

@Override
public void dispatch() {
dispatchers.forEach(MessagePolyDispatcher::dispatch);
}

@Override
public CompletableFuture<Void> dispatchAsync() {
return dispatchers.stream()
.map(MessagePolyDispatcher::dispatchAsync)
.collect(CompletableFutures.joinList())
.thenAccept(__ -> {});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.shiza.honey.adventure.message.dispatcher;

import dev.shiza.honey.message.dispatcher.MessageBaseDispatcher;
import dev.shiza.honey.message.dispatcher.MessageDispatcher;
import dev.shiza.honey.message.dispatcher.TitleMessageDispatcher;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;

/**
* AdventureMessageDispatcher provides static factory methods to create various types of message
* dispatchers for use in an adventure game context. This class cannot be instantiated and provides
* centralized access to functions creating dispatchers for chat messages, action bars, and titles.
*/
public final class AdventureMessageDispatcher {

private AdventureMessageDispatcher() {}

/**
* Creates a MessageDispatcher for sending chat messages.
*
* @return A MessageDispatcher instance configured to send chat messages to an Audience.
*/
public static MessageDispatcher<Audience, Component> createChat() {
return new MessageBaseDispatcher<>(Audience.empty(), Audience::sendMessage);
}

/**
* Creates a MessageDispatcher for sending action bar messages.
*
* @return A MessageDispatcher instance configured to send action bar messages to an Audience.
*/
public static MessageDispatcher<Audience, Component> createActionBar() {
return new MessageBaseDispatcher<>(Audience.empty(), Audience::sendActionBar);
}

/**
* Creates a TitleMessageDispatcher for sending title messages.
*
* @return A TitleMessageDispatcher instance configured to send title messages to an Audience.
*/
public static TitleMessageDispatcher<Audience, Component> createTitle() {
return new AdventureTitleMessageDispatcher();
}
}
Loading

0 comments on commit 279e85c

Please sign in to comment.