Skip to content

Commit

Permalink
Rewrite adventure item translation support
Browse files Browse the repository at this point in the history
  • Loading branch information
booky10 committed May 27, 2024
1 parent 9aac881 commit a4384b1
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ From: booky10 <[email protected]>
Date: Sun, 22 Aug 2021 20:30:16 +0200
Subject: [PATCH] Add option to translate custom item names and lore

This patch was completely rewritten with the 1.20.5/1.20.6 update

diff --git a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
index 26e393051d2c5fe84b8ae6a33b376efab6198816..b21f7a41581ddf36d61e206366c6398738a47813 100644
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,11 @@ Subject: [PATCH] Split item lore lines on newline characters
The client doesn't respect newlines, so
this has to be done at the network level

diff --git a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
index 26e393051d2c5fe84b8ae6a33b376efab6198816..4672e336eada51d1dc6b6b7415392a8598634c16 100644
--- a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
+++ b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
@@ -107,4 +107,10 @@ public class CloudPlaneConfig {
private static Component getComponent(String path, Component def) {
return MiniMessage.miniMessage().deserialize(getString(path, MiniMessage.miniMessage().serialize(def)));
}
+
+ private static void adventure() {
+ if (version <= 4) {
+ set("settings.settings.translate-items", null);
+ }
+ }
}
diff --git a/src/main/java/dev/booky/cloudplane/ComponentUtil.java b/src/main/java/dev/booky/cloudplane/ComponentUtil.java
diff --git a/src/main/java/dev/booky/cloudplane/ItemUtil.java b/src/main/java/dev/booky/cloudplane/ItemUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..11b8bdfc16620bbd8762d41c59642d552982c65b
index 0000000000000000000000000000000000000000..cc19d9e75233465cbf28f65aecfdf498d4339a63
--- /dev/null
+++ b/src/main/java/dev/booky/cloudplane/ComponentUtil.java
+++ b/src/main/java/dev/booky/cloudplane/ItemUtil.java
@@ -0,0 +1,66 @@
+package dev.booky.cloudplane;
+
Expand All @@ -37,9 +22,9 @@ index 0000000000000000000000000000000000000000..11b8bdfc16620bbd8762d41c59642d55
+import java.util.Collections;
+import java.util.List;
+
+public final class ComponentUtil {
+public final class ItemUtil {
+
+ private ComponentUtil() {
+ private ItemUtil() {
+ }
+
+ private static List<Component> inlineComponent(Component component) {
Expand Down Expand Up @@ -94,7 +79,7 @@ index 0000000000000000000000000000000000000000..11b8bdfc16620bbd8762d41c59642d55
+ }
+}
diff --git a/src/main/java/net/minecraft/core/component/DataComponents.java b/src/main/java/net/minecraft/core/component/DataComponents.java
index 5632974af9c603d333ffc30a5a1b1e851821a3bb..dfc505afb0ef2ebb5673d61065d7d0eed5024a38 100644
index 9b2a209cda955ef3e5d8ff3ed1b2249888c7d139..de0f853ca0090de9c4fb0f54a87d25ef783b533e 100644
--- a/src/main/java/net/minecraft/core/component/DataComponents.java
+++ b/src/main/java/net/minecraft/core/component/DataComponents.java
@@ -74,7 +74,7 @@ public class DataComponents {
Expand All @@ -107,7 +92,7 @@ index 5632974af9c603d333ffc30a5a1b1e851821a3bb..dfc505afb0ef2ebb5673d61065d7d0ee
public static final DataComponentType<Rarity> RARITY = register(
"rarity", builder -> builder.persistent(Rarity.CODEC).networkSynchronized(Rarity.STREAM_CODEC)
diff --git a/src/main/java/net/minecraft/world/item/component/ItemLore.java b/src/main/java/net/minecraft/world/item/component/ItemLore.java
index ce17a9256b7d7e649ee90769ab561917b20514f9..6ec394939ffb8c53f2ffb57d58e54336aae8f1b2 100644
index ce17a9256b7d7e649ee90769ab561917b20514f9..e4bc72ffd982a06a71bfa1c20f4e66e13cf3234a 100644
--- a/src/main/java/net/minecraft/world/item/component/ItemLore.java
+++ b/src/main/java/net/minecraft/world/item/component/ItemLore.java
@@ -25,6 +25,25 @@ public record ItemLore(List<Component> lines, List<Component> styledLines) imple
Expand All @@ -124,7 +109,7 @@ index ce17a9256b7d7e649ee90769ab561917b20514f9..6ec394939ffb8c53f2ffb57d58e54336
+ List<Component> realLines = new java.util.ArrayList<>(lines.size() * 2);
+ for (Component line : lines) {
+ net.kyori.adventure.text.Component advLine = io.papermc.paper.adventure.PaperAdventure.asAdventure(line);
+ for (net.kyori.adventure.text.Component realLine : dev.booky.cloudplane.ComponentUtil.getLines(advLine)) {
+ for (net.kyori.adventure.text.Component realLine : dev.booky.cloudplane.ItemUtil.getLines(advLine)) {
+ realLines.add(io.papermc.paper.adventure.PaperAdventure.asVanilla(realLine));
+ }
+ }
Expand Down
8 changes: 4 additions & 4 deletions patches/server/0006-Add-more-detailed-brand-info.patch
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ Subject: [PATCH] Add more detailed brand info
Sends version info to player in brand packet

diff --git a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
index 4672e336eada51d1dc6b6b7415392a8598634c16..7352b9094917b57cae64198570c8768d595a5123 100644
index 26e393051d2c5fe84b8ae6a33b376efab6198816..b3402ff1789cf0e2ec661282a3ee7bad3f627041 100644
--- a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
+++ b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
@@ -113,4 +113,14 @@ public class CloudPlaneConfig {
set("settings.settings.translate-items", null);
}
@@ -107,4 +107,14 @@ public class CloudPlaneConfig {
private static Component getComponent(String path, Component def) {
return MiniMessage.miniMessage().deserialize(getString(path, MiniMessage.miniMessage().serialize(def)));
}
+
+ public static boolean detailedBrand = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: booky10 <[email protected]>
Date: Mon, 27 May 2024 03:13:37 +0200
Subject: [PATCH] Add option to translate custom item names and lore


diff --git a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
index b3402ff1789cf0e2ec661282a3ee7bad3f627041..ec8bdaa81a924e7d5eaf5c74b1c4cc2121fa3c8e 100644
--- a/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
+++ b/src/main/java/dev/booky/cloudplane/CloudPlaneConfig.java
@@ -117,4 +117,20 @@ public class CloudPlaneConfig {
}
detailedBrand = getBoolean("settings.detailed-brand-info", detailedBrand);
}
+
+ public static boolean localizeItems = true;
+ private static void adventure() {
+ if (version <= 2) {
+ localizeItems = getBoolean("settings.localize.items", localizeItems);
+ set("settings.adventure.localize-items", localizeItems);
+ set("settings.localize", null);
+ }
+ if (version <= 3) {
+ localizeItems = getBoolean("settings.adventure.localize-items", localizeItems);
+ set("settings.translate-items", localizeItems);
+ set("settings.adventure", null);
+ }
+
+ localizeItems = getBoolean("settings.translate-items", localizeItems);
+ }
}
diff --git a/src/main/java/dev/booky/cloudplane/ItemUtil.java b/src/main/java/dev/booky/cloudplane/ItemUtil.java
index cc19d9e75233465cbf28f65aecfdf498d4339a63..0117a2c5a714e9c9140380a51883b7fbc48bdf1e 100644
--- a/src/main/java/dev/booky/cloudplane/ItemUtil.java
+++ b/src/main/java/dev/booky/cloudplane/ItemUtil.java
@@ -1,18 +1,99 @@
package dev.booky.cloudplane;

+import com.mojang.datafixers.util.Pair;
+import com.mojang.serialization.Codec;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
+import net.minecraft.core.component.DataComponentPatch;
+import net.minecraft.core.component.DataComponentType;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtOps;
+import net.minecraft.nbt.Tag;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.component.CustomData;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static net.minecraft.core.component.DataComponents.CUSTOM_DATA;

public final class ItemUtil {

+ private static final List<Pair<String, DataComponentType<?>>> SAVEABLE_COMPONENT_TYPES = Stream.of(
+ DataComponents.ITEM_NAME, DataComponents.CUSTOM_NAME, DataComponents.LORE
+ )
+ .<Pair<String, DataComponentType<?>>>map(type -> Pair.of(BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(type).toString(), type))
+ .toList();
+ private static final String SAVEABLE_COMPONENT_TAG_NAME = "CloudPlane$SavedData";
+
private ItemUtil() {
}

+ @SuppressWarnings("unchecked") // not unchecked
+ public static void unpackPatchSaves(ItemStack stack) {
+ CustomData customData = stack.getOrDefault(CUSTOM_DATA, CustomData.EMPTY);
+ if (customData.isEmpty() || !customData.contains(SAVEABLE_COMPONENT_TAG_NAME)) {
+ return; // nothing to unpack
+ }
+ CompoundTag savedTag = customData.getUnsafe().getCompound(SAVEABLE_COMPONENT_TAG_NAME);
+ for (Pair<String, DataComponentType<?>> type : SAVEABLE_COMPONENT_TYPES) {
+ Tag encoded = savedTag.get(type.getFirst());
+ if (encoded == null) {
+ continue; // nothing saved for this type, skip
+ }
+ Object decoded = type.getSecond().codecOrThrow()
+ .decode(NbtOps.INSTANCE, encoded)
+ .getOrThrow().getFirst();
+ stack.set((DataComponentType<Object>) type.getSecond(), decoded);
+ }
+ // generally unsafe to do, but this probably won't cause any issues at this place
+ customData.getUnsafe().remove(SAVEABLE_COMPONENT_TAG_NAME);
+ }
+
+ @SuppressWarnings("unchecked") // not unchecked
+ public static DataComponentPatch packPatchSaves(ItemStack stack) {
+ Reference2ObjectMap<DataComponentType<?>, Optional<?>> patch = stack.components.patch;
+ if (patch == null || patch.isEmpty()) {
+ return DataComponentPatch.EMPTY; // no patches, skip complex logic
+ }
+
+ CompoundTag savedTag = null; // lazy-loaded
+ for (Pair<String, DataComponentType<?>> type : SAVEABLE_COMPONENT_TYPES) {
+ Optional<?> value = patch.get(type.getSecond());
+ if (value == null || value.isEmpty()) {
+ continue;
+ }
+ if (savedTag == null) {
+ savedTag = new CompoundTag();
+ }
+ Codec<Object> codec = ((DataComponentType<Object>) type.getSecond()).codecOrThrow();
+ Tag encoded = codec.encodeStart(NbtOps.INSTANCE, value.get()).getOrThrow();
+ savedTag.put(type.getFirst(), encoded);
+ }
+ if (savedTag == null) { // nothing found to be saved, return original
+ return new DataComponentPatch(patch);
+ }
+
+ // add saved data to custom data component
+ CompoundTag tag = stack.getOrDefault(CUSTOM_DATA, CustomData.EMPTY).copyTag();
+ tag.put(SAVEABLE_COMPONENT_TAG_NAME, savedTag);
+
+ // copy patch map, prevents modification of original item stack
+ Reference2ObjectMap<DataComponentType<?>, Optional<?>> newPatch =
+ new Reference2ObjectArrayMap<>(patch.size() + 1);
+ newPatch.putAll(patch);
+ newPatch.put(CUSTOM_DATA, Optional.of(CustomData.of(tag)));
+ return new DataComponentPatch(newPatch);
+ }
+
private static List<Component> inlineComponent(Component component) {
component = component.compact();
if (component.children().isEmpty()) {
diff --git a/src/main/java/net/minecraft/core/component/DataComponentPatch.java b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
index b8977749d35dd7343021425f477445bec470d46b..c94e5ed9d61f1586a08ce1ec6ea032eb4d2603a4 100644
--- a/src/main/java/net/minecraft/core/component/DataComponentPatch.java
+++ b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
@@ -155,7 +155,7 @@ public final class DataComponentPatch {
private static final String REMOVED_PREFIX = "!";
final Reference2ObjectMap<DataComponentType<?>, Optional<?>> map;

- DataComponentPatch(Reference2ObjectMap<DataComponentType<?>, Optional<?>> changedComponents) {
+ public DataComponentPatch(Reference2ObjectMap<DataComponentType<?>, Optional<?>> changedComponents) { // CloudPlane - package-private -> public
this.map = changedComponents;
}

diff --git a/src/main/java/net/minecraft/core/component/PatchedDataComponentMap.java b/src/main/java/net/minecraft/core/component/PatchedDataComponentMap.java
index 22da75d8197de29a150c9eade7994deecae53a10..c026a6edf497c86be3b3f1b511bb285701173a88 100644
--- a/src/main/java/net/minecraft/core/component/PatchedDataComponentMap.java
+++ b/src/main/java/net/minecraft/core/component/PatchedDataComponentMap.java
@@ -16,7 +16,7 @@ import javax.annotation.Nullable;

public final class PatchedDataComponentMap implements DataComponentMap {
private final DataComponentMap prototype;
- private Reference2ObjectMap<DataComponentType<?>, Optional<?>> patch;
+ public Reference2ObjectMap<DataComponentType<?>, Optional<?>> patch; // CloudPlane - private -> public
private boolean copyOnWrite;

public PatchedDataComponentMap(DataComponentMap baseComponents) {
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 58c38bc4361ddf24716f326b0c6fc626d434756e..24d035a40c675ce55893169c74101a9c392cac44 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -171,6 +171,11 @@ public final class ItemStack implements DataComponentHolder {
if (false && !datacomponentpatch.isEmpty()) { // Paper - This is no longer needed with raw NBT being handled in metadata
CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
}
+ // CloudPlane start - item localization
+ if (dev.booky.cloudplane.CloudPlaneConfig.localizeItems) {
+ dev.booky.cloudplane.ItemUtil.unpackPatchSaves(itemstack);
+ }
+ // CloudPlane end - item localization
return itemstack;
// CraftBukkit end
}
@@ -186,15 +191,23 @@ public final class ItemStack implements DataComponentHolder {
// CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer with raw NBT being handled in metadata
// Spigot end
ITEM_STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.getItemHolder()); // CraftBukkit - decompile error
+ // CloudPlane start - item localization
+ if (dev.booky.cloudplane.CloudPlaneConfig.localizeItems
+ && registryfriendlybytebuf.adventure$locale != null) {
+ DataComponentPatch.STREAM_CODEC.encode(registryfriendlybytebuf,
+ dev.booky.cloudplane.ItemUtil.packPatchSaves(itemstack));
+ } else {
+ // CloudPlane end - item localization
// Paper start - adventure; conditionally render translatable components
boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
try {
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
- DataComponentPatch.STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.components.asPatch());
+ DataComponentPatch.STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.components.asPatch()); // CloudPlane - item localization; diff on change
} finally {
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
}
// Paper end - adventure; conditionally render translatable components
+ } // CloudPlane - item localization
}
}
};
@@ -228,7 +241,7 @@ public final class ItemStack implements DataComponentHolder {
@Deprecated
@Nullable
private Item item;
- private PatchedDataComponentMap components;
+ public PatchedDataComponentMap components; // CloudPlane - private -> public
@Nullable
private Entity entityRepresentation;

diff --git a/src/main/java/net/minecraft/world/item/component/ItemLore.java b/src/main/java/net/minecraft/world/item/component/ItemLore.java
index e4bc72ffd982a06a71bfa1c20f4e66e13cf3234a..cda383fb63889177a96e85f41151dce92a891692 100644
--- a/src/main/java/net/minecraft/world/item/component/ItemLore.java
+++ b/src/main/java/net/minecraft/world/item/component/ItemLore.java
@@ -41,6 +41,36 @@ public record ItemLore(List<Component> lines, List<Component> styledLines) imple
}
return realLines;
})
+ // CloudPlane start - item localization; line splitting support
+ .<List<Component>>apply(codec -> new StreamCodec<>() {
+ @Override
+ public List<Component> decode(RegistryFriendlyByteBuf buf) {
+ return codec.decode(buf);
+ }
+
+ @Override
+ public void encode(RegistryFriendlyByteBuf buf, List<Component> value) {
+ if (dev.booky.cloudplane.CloudPlaneConfig.localizeItems && buf.adventure$locale != null) {
+ // pre-render translations here to work around line splitting not working anymore
+ boolean prevNoRender = ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
+ try {
+ ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
+ List<Component> lines = Lists.newArrayListWithCapacity(value.size());
+ for (Component line : value) {
+ net.kyori.adventure.text.Component advLine = io.papermc.paper.adventure.PaperAdventure.asAdventure(line);
+ net.kyori.adventure.text.Component i18nLine = net.kyori.adventure.translation.GlobalTranslator.render(advLine, buf.adventure$locale);
+ lines.add(io.papermc.paper.adventure.PaperAdventure.asVanilla(i18nLine));
+ }
+ codec.encode(buf, lines);
+ } finally {
+ ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prevNoRender);
+ }
+ } else {
+ codec.encode(buf, value);
+ }
+ }
+ })
+ // CloudPlane end - item localization; line splitting support
.map(ItemLore::new, ItemLore::lines);
// CloudPlane end - split lore lines

0 comments on commit a4384b1

Please sign in to comment.