Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public record SignLayout(
@NonNull List<String> lines,
@NonNull String blockMaterial,
int blockSubId,
@Nullable String glowingColor
@Nullable String textColor,
boolean textGlowing
) {

public static @NonNull Builder builder() {
Expand All @@ -39,15 +40,17 @@ public record SignLayout(
.lines(new ArrayList<>(signLayout.lines()))
.blockMaterial(signLayout.blockMaterial())
.blockSubId(signLayout.blockSubId())
.glowingColor(signLayout.glowingColor());
.textColor(signLayout.textColor())
.textGlowing(signLayout.textGlowing());
}

public static class Builder {

private List<String> lines;
private String blockMaterial;
private int blockSubId = -1;
private String glowingColor;
private String textColor;
private boolean textGlowing;

public @NonNull Builder lines(@NonNull Collection<String> lines) {
this.lines = new ArrayList<>(lines);
Expand All @@ -68,17 +71,21 @@ public static class Builder {
return this;
}

public @NonNull Builder glowingColor(@Nullable String glowingColor) {
this.glowingColor = glowingColor;
public @NonNull Builder textColor(@Nullable String textColor) {
this.textColor = textColor;
return this;
}

public @NonNull Builder textGlowing(boolean textGlowing) {
this.textGlowing = textGlowing;
return this;
}

public @NonNull SignLayout build() {
Preconditions.checkNotNull(this.lines, "Missing lines");
Preconditions.checkNotNull(this.blockMaterial, "Missing block material");

return new SignLayout(this.lines, this.blockMaterial, this.blockSubId, this.glowingColor);
return new SignLayout(this.lines, this.blockMaterial, this.blockSubId, this.textColor, this.textGlowing);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
import eu.cloudnetservice.modules.signs.configuration.SignsConfiguration;
import eu.cloudnetservice.modules.signs.impl._deprecated.configuration.SignConfigurationReaderAndWriter;
import eu.cloudnetservice.modules.signs.impl._deprecated.configuration.entry.SignLayoutConfiguration;
import io.leangen.geantyref.TypeFactory;
import java.lang.reflect.Type;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import lombok.NonNull;
import org.jetbrains.annotations.Contract;
Expand All @@ -47,25 +50,104 @@ public static void write(@NonNull SignsConfiguration configuration, @NonNull Pat
public static SignsConfiguration read(@NonNull Path path) {
var configurationDocument = DocumentFactory.json().parse(path);
if (configurationDocument.contains("config")) {
// write the new configuration file
// convert the old v3 configuration
var configuration = convertOldConfiguration(configurationDocument, path);
write(configuration, path);
// notify that the convert was successful
LOGGER.info("Successfully converted the old signs configuration file");
// no need to load the configuration from the file again
return configuration;
}
// check if the configuration file already exists

if (configurationDocument.empty()) {
// create a new configuration entry
// initial config load: create a new, blank config entry
var configuration = SignsConfiguration.builder()
.modifyEntries(entries -> entries.add(SignConfigurationType.JAVA.createEntry("Lobby")))
.build();
write(configuration, path);
return configuration;
}
// the document contains a configuration
return configurationDocument.toInstanceOf(SignsConfiguration.class);

// document contains a modern configuration, load that - migrate if necessary
convertGlowingColor(configurationDocument);
var configuration = configurationDocument.toInstanceOf(SignsConfiguration.class);
write(configuration, path);
return configuration;
}

/**
* Converts the old {@code glowingColor} setting for all config entries in the given config document.
*
* @param configDocument the config document to convert.
* @throws NullPointerException if the given config document is null.
*/
private static void convertGlowingColor(@NonNull Document.Mutable configDocument) {
var listDocumentType = TypeFactory.parameterizedClass(List.class, Document.class);
var layoutNames = List.of("searchingLayout", "startingLayout", "emptyLayout", "onlineLayout", "fullLayout");

List<Document> configEntries = configDocument.readObject("entries", listDocumentType);
for (var entryIndex = 0; entryIndex < configEntries.size(); entryIndex++) {
// convert top-level layouts
var configEntry = configEntries.get(entryIndex).mutableCopy();
convertGlowingInConfig(configEntry, listDocumentType, layoutNames);

// convert group-level layouts
List<Document> groupConfigurations = configEntry.readObject("groupConfigurations", listDocumentType);
for (var groupIndex = 0; groupIndex < groupConfigurations.size(); groupIndex++) {
var groupConfig = groupConfigurations.get(groupIndex).mutableCopy();
convertGlowingInConfig(groupConfig, listDocumentType, layoutNames);
groupConfigurations.set(groupIndex, groupConfig);
}
configEntry.append("groupConfigurations", groupConfigurations);

// update the config entry
configEntries.set(entryIndex, configEntry);
}

// copy the modified config entries into the source document
configDocument.append("entries", configEntries);
}

/**
* Converts the old {@code glowingColor} setting for all layout holders in the given config document.
*
* @param config the config document to convert.
* @param listDocumentType type representing a list of documents.
* @param layoutNames the layout property names to convert.
* @throws NullPointerException if the given config document, list type or layout names is null.
*/
private static void convertGlowingInConfig(
@NonNull Document.Mutable config,
@NonNull Type listDocumentType,
@NonNull List<String> layoutNames
) {
for (var layoutName : layoutNames) {
var holder = config.readMutableDocument(layoutName, null);
if (holder != null) {
List<Document> layouts = holder.readObject("signLayouts", listDocumentType);
for (var index = 0; index < layouts.size(); index++) {
var layout = layouts.get(index).mutableCopy();
if (layout.contains("glowingColor")) {
var glowingColor = layout.getString("glowingColor");
if (glowingColor != null) {
// glowing color was set, enable text color and glowing
layout.append("textColor", glowingColor);
layout.append("textGlowing", true);
} else {
// glowing color was not set, no need to enable text color or glowing
layout.appendNull("textColor");
layout.append("textGlowing", false);
}

// remove old glowing color property, update document
layout.remove("glowingColor");
layouts.set(index, layout);
}
}

// update the sign layouts with the modified variant in the holder document and then in the original config
holder.append("signLayouts", layouts);
config.append(layoutName, holder);
}
}
}

// convert of old configuration file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,23 +284,40 @@ private static void logExceptionMessage(@NonNull String baseMessage, @Nullable S
}

/**
* Enables the glowing effect for the given signs if the layout has a glowing color defined.
* Applies the text color defined in the given layout to the given sign. Falls back to black if not defined.
*
* @param sign the sign to apply the text color to.
* @param layout the layout to get the text color from.
* @throws NullPointerException if the given sign or layout is null.
*/
public static void signTextColor(@NonNull org.bukkit.block.Sign sign, @NonNull SignLayout layout) {
if (SIGN_SET_TEXT_COLOR != null) {
try {
var textColor = layout.textColor();
var dyeColor = switch (textColor) {
case String string -> Enums.getIfPresent(DyeColor.class, StringUtil.toUpper(string)).or(DyeColor.BLACK);
case null -> DyeColor.BLACK;
};
SIGN_SET_TEXT_COLOR.apply(sign, dyeColor);
} catch (Throwable throwable) {
logExceptionMessage("Unable to set sign text color: {}", throwable.getMessage());
}
}
}

/**
* Enables the glowing effect for the given signs if the given layout has that feature enabled.
*
* @param sign the sign to enable the glowing effect for.
* @param layout the layout to resolve the glowing effect from.
* @throws NullPointerException if the given target sign or sign layout is null.
*/
public static void signGlowing(@NonNull org.bukkit.block.Sign sign, @NonNull SignLayout layout) {
var glowingColor = layout.glowingColor();
if (SIGN_SET_GLOWING != null && SIGN_SET_TEXT_COLOR != null && glowingColor != null) {
if (SIGN_SET_GLOWING != null) {
try {
var dyeColor = Enums.getIfPresent(DyeColor.class, StringUtil.toUpper(glowingColor)).orNull();
if (dyeColor != null) {
SIGN_SET_GLOWING.apply(sign, Boolean.TRUE);
SIGN_SET_TEXT_COLOR.apply(sign, dyeColor);
}
SIGN_SET_GLOWING.apply(sign, layout.textGlowing());
} catch (Throwable throwable) {
logExceptionMessage("Unable to sign glowing: {}", throwable.getMessage());
logExceptionMessage("Unable to set sign glowing: {}", throwable.getMessage());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public boolean needsUpdates() {
// check if the associated chunk is loaded
var chunkX = NumberConversions.floor(location.getX()) >> 4;
var chunkZ = NumberConversions.floor(location.getZ()) >> 4;

return location.getWorld().isChunkLoaded(chunkX, chunkZ);
}

Expand All @@ -90,11 +89,11 @@ public void updateSign(@NonNull SignLayout layout) {
return;
}

// get the block at the given location
var state = location.getBlock().getState();
if (state instanceof org.bukkit.block.Sign sign) {
// set the glowing status if needed
// set the text color and glowing state
BukkitCompatibility.signGlowing(sign, layout);
BukkitCompatibility.signTextColor(sign, layout);

// set the sign lines
this.changeSignLines(layout, (line, text) -> BukkitCompatibility.signLine(sign, line, text));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,32 @@

package eu.cloudnetservice.modules.signs.impl.platform.minestom;

import com.google.common.base.Enums;
import eu.cloudnetservice.driver.registry.ServiceRegistry;
import eu.cloudnetservice.driver.service.ServiceInfoSnapshot;
import eu.cloudnetservice.ext.adventure.AdventureTextFormatLookup;
import eu.cloudnetservice.ext.component.ComponentFormats;
import eu.cloudnetservice.modules.signs.Sign;
import eu.cloudnetservice.modules.signs.configuration.SignLayout;
import eu.cloudnetservice.modules.signs.impl.platform.PlatformSign;
import eu.cloudnetservice.modules.signs.impl.platform.minestom.event.MinestomCloudSignInteractEvent;
import eu.cloudnetservice.utils.base.StringUtil;
import io.vavr.Tuple2;
import java.util.UUID;
import lombok.NonNull;
import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.nbt.ListBinaryTag;
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
import net.minestom.server.codec.Transcoder;
import net.minestom.server.color.DyeColor;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Player;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceManager;
import org.jetbrains.annotations.Nullable;

public class MinestomPlatformSign extends PlatformSign<Player, String> {
public class MinestomPlatformSign extends PlatformSign<Player, BinaryTag> {

private final GlobalEventHandler eventHandler;
private final InstanceManager instanceManager;
Expand All @@ -52,7 +56,7 @@ public MinestomPlatformSign(
) {
super(base, serviceRegistry, input -> {
var coloredComponent = ComponentFormats.BUNGEE_TO_ADVENTURE.convert(input);
return GsonComponentSerializer.gson().serialize(coloredComponent);
return NbtComponentSerializer.nbt().serialize(coloredComponent);
});

this.eventHandler = eventHandler;
Expand Down Expand Up @@ -86,27 +90,37 @@ public boolean needsUpdates() {
public void updateSign(@NonNull SignLayout layout) {
var location = this.signLocation();
if (location != null) {

// construct the sign data in this binary compound
var compound = CompoundBinaryTag.builder();

// set the sign glowing if requested
var glowingColor = layout.glowingColor();
if (glowingColor != null && glowingColor.length() == 1) {
var color = AdventureTextFormatLookup.findColor(glowingColor.charAt(0));

compound.putBoolean("GlowingText", color != null);
compound.putString("Color", color == null ? NamedTextColor.WHITE.toString() : color.toString());
}

// set the sign lines
this.changeSignLines(layout, (index, line) -> compound.putString("Text" + (index + 1), line));
// set the glowing state
var textCompound = CompoundBinaryTag.builder();
textCompound.putBoolean("has_glowing_text", layout.textGlowing());

// set the text color
var textColor = layout.textColor();
var dyeColor = switch (textColor) {
case String string -> Enums.getIfPresent(DyeColor.class, StringUtil.toUpper(string)).or(DyeColor.BLACK);
case null -> DyeColor.BLACK;
};
var serializedColor = DyeColor.CODEC
.encode(Transcoder.NBT, dyeColor)
.orElseThrow("could not transcode dye color " + dyeColor + " to nbt");
textCompound.put("color", serializedColor);

// set the sign lines - they are provided as legacy text components and need to be converted to JSON
var linesCompound = ListBinaryTag.builder();
this.changeSignLines(layout, (_, line) -> linesCompound.add(line));
textCompound.put("messages", linesCompound.build());

// build the final sign compound
var signCompound = CompoundBinaryTag.builder();
signCompound.putBoolean("is_waxed", false);
signCompound.put("front_text", textCompound.build());
signCompound.put("back_text", textCompound.build());

// set the block at the position
var block = location._2().getBlock(location._1());
location._2().setBlock(
location._1(),
block.withHandler(MinestomSignBlockHandler.SIGN_BLOCK_HANDLER).withNbt(compound.build()));
block.withHandler(MinestomSignBlockHandler.SIGN_BLOCK_HANDLER).withNbt(signCompound.build()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,29 @@
final class MinestomSignBlockHandler implements BlockHandler {

public static final MinestomSignBlockHandler SIGN_BLOCK_HANDLER = new MinestomSignBlockHandler();
private static final List<Tag<?>> ENTITY_TAGS = List.of(
Tag.Byte("GlowingText"),
Tag.String("Color"),
Tag.String("Text1"),
Tag.String("Text2"),
Tag.String("Text3"),
Tag.String("Text4"));

private static final Key SIGN_NAMESPACE = Key.key("minecraft", "sign");
private static final List<Tag<?>> SIGN_ENTITY_TAGS = List.of(
Tag.Byte("is_waxed"),
Tag.NBT("front_text"),
Tag.NBT("back_text"));

private MinestomSignBlockHandler() {
}

/**
* {@inheritDoc}
*/
@Override
public @NonNull Collection<Tag<?>> getBlockEntityTags() {
return ENTITY_TAGS;
public @NonNull Key getKey() {
return SIGN_NAMESPACE;
}

/**
* {@inheritDoc}
*/
@Override
public @NonNull Key getKey() {
return SIGN_NAMESPACE;
public @NonNull Collection<Tag<?>> getBlockEntityTags() {
return SIGN_ENTITY_TAGS;
}
}
Loading
Loading