Skip to content

Commit 788a244

Browse files
committed
feat(core): translate items with packetevents
1 parent bf6beb3 commit 788a244

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed

core/src/main/java/com/rexcantor64/triton/packetinterceptor/PacketEventsListener.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.rexcantor64.triton.packetinterceptor.handlers.DisconnectPacketHandler;
1515
import com.rexcantor64.triton.packetinterceptor.handlers.EntityPacketHandler;
1616
import com.rexcantor64.triton.packetinterceptor.handlers.GuiPacketHandler;
17+
import com.rexcantor64.triton.packetinterceptor.handlers.ItemPacketHandler;
1718
import com.rexcantor64.triton.packetinterceptor.handlers.ResourcePackPacketHandler;
1819
import com.rexcantor64.triton.packetinterceptor.handlers.ScoreboardPacketHandler;
1920
import com.rexcantor64.triton.packetinterceptor.handlers.TabPacketHandler;
@@ -141,6 +142,13 @@ public void setupHandlers() {
141142

142143
updatedHandlers.put(PacketType.Play.Server.JOIN_GAME, entityHandler::onJoinGame);
143144
}
145+
if (config.isItems()) {
146+
val itemHandler = new ItemPacketHandler(parser, config);
147+
updatedHandlers.put(PacketType.Play.Server.SET_CURSOR_ITEM, itemHandler::onSetCursorItemPacket);
148+
updatedHandlers.put(PacketType.Play.Server.SET_PLAYER_INVENTORY, itemHandler::onSetPlayerInventoryPacket);
149+
updatedHandlers.put(PacketType.Play.Server.SET_SLOT, itemHandler::onSetSlotPacket);
150+
updatedHandlers.put(PacketType.Play.Server.WINDOW_ITEMS, itemHandler::onWindowItemsPacket);
151+
}
144152

145153
receiveHandlers = Collections.unmodifiableMap(updatedHandlers);
146154
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package com.rexcantor64.triton.packetinterceptor.handlers;
2+
3+
import com.github.retrooper.packetevents.event.PacketSendEvent;
4+
import com.github.retrooper.packetevents.protocol.component.ComponentTypes;
5+
import com.github.retrooper.packetevents.protocol.item.ItemStack;
6+
import com.github.retrooper.packetevents.util.Filterable;
7+
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetCursorItem;
8+
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPlayerInventory;
9+
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetSlot;
10+
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerWindowItems;
11+
import com.rexcantor64.triton.api.language.Localized;
12+
import com.rexcantor64.triton.config.MainConfig;
13+
import com.rexcantor64.triton.language.parser.MessageParser;
14+
import com.rexcantor64.triton.player.TritonLanguagePlayer;
15+
import com.rexcantor64.triton.utils.ComponentUtils;
16+
import lombok.RequiredArgsConstructor;
17+
import lombok.val;
18+
import net.kyori.adventure.text.Component;
19+
import org.jetbrains.annotations.NotNull;
20+
21+
import java.util.ArrayList;
22+
import java.util.Iterator;
23+
import java.util.List;
24+
import java.util.concurrent.atomic.AtomicBoolean;
25+
import java.util.stream.Collectors;
26+
27+
@RequiredArgsConstructor
28+
public class ItemPacketHandler {
29+
30+
private final @NotNull MessageParser parser;
31+
private final @NotNull MainConfig.FeatureSyntax syntax;
32+
33+
public ItemPacketHandler(@NotNull MessageParser parser, @NotNull MainConfig config) {
34+
this.parser = parser;
35+
this.syntax = config.getItemsSyntax();
36+
}
37+
38+
public void onSetCursorItemPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
39+
val packet = new WrapperPlayServerSetCursorItem(event);
40+
41+
val changed = translateItem(packet.getStack(), languagePlayer);
42+
if (changed) {
43+
event.markForReEncode(true);
44+
}
45+
}
46+
47+
public void onSetPlayerInventoryPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
48+
val packet = new WrapperPlayServerSetPlayerInventory(event);
49+
50+
val changed = translateItem(packet.getStack(), languagePlayer);
51+
if (changed) {
52+
event.markForReEncode(true);
53+
}
54+
}
55+
56+
public void onSetSlotPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
57+
val packet = new WrapperPlayServerSetSlot(event);
58+
59+
val changed = translateItem(packet.getItem(), languagePlayer);
60+
if (changed) {
61+
event.markForReEncode(true);
62+
}
63+
}
64+
65+
public void onWindowItemsPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
66+
val packet = new WrapperPlayServerWindowItems(event);
67+
68+
boolean changed = false;
69+
val carriedItem = packet.getCarriedItem();
70+
if (carriedItem.isPresent()) {
71+
changed |= translateItem(carriedItem.get(), languagePlayer);
72+
73+
}
74+
for (val item : packet.getItems()) {
75+
changed |= translateItem(item, languagePlayer);
76+
}
77+
78+
if (changed) {
79+
event.markForReEncode(true);
80+
}
81+
}
82+
83+
private boolean translateItem(ItemStack item, Localized locale) {
84+
return translateItem(item, locale, true, true);
85+
}
86+
87+
private boolean translateItem(ItemStack item, Localized locale, boolean translateLore, boolean translateBook) {
88+
boolean changed = false;
89+
90+
changed |= translateItemName(item, locale);
91+
changed |= translateCustomName(item, locale);
92+
if (translateLore) {
93+
changed |= translateLore(item, locale);
94+
changed |= translateContainerContents(item, locale);
95+
}
96+
if (translateBook) {
97+
changed |= translateBook(item, locale);
98+
}
99+
100+
return changed;
101+
}
102+
103+
private boolean translateItemName(ItemStack item, Localized locale) {
104+
val itemNameOpt = item.getComponent(ComponentTypes.ITEM_NAME);
105+
if (!itemNameOpt.isPresent()) {
106+
return false;
107+
}
108+
109+
val itemName = itemNameOpt.get();
110+
val translationResult = parser.translateComponent(
111+
itemName,
112+
locale,
113+
this.syntax
114+
);
115+
116+
translationResult
117+
.map(ComponentUtils::ensureNotItalic)
118+
.ifChanged(result -> item.setComponent(ComponentTypes.ITEM_NAME, result))
119+
.ifToRemove(() -> item.unsetComponent(ComponentTypes.ITEM_NAME));
120+
121+
return !translationResult.isUnchanged();
122+
}
123+
124+
private boolean translateCustomName(ItemStack item, Localized locale) {
125+
val itemNameOpt = item.getComponent(ComponentTypes.CUSTOM_NAME);
126+
if (!itemNameOpt.isPresent()) {
127+
return false;
128+
}
129+
130+
val itemName = itemNameOpt.get();
131+
val translationResult = parser.translateComponent(
132+
itemName,
133+
locale,
134+
this.syntax
135+
);
136+
137+
translationResult
138+
.map(ComponentUtils::ensureNotItalic)
139+
.ifChanged(result -> item.setComponent(ComponentTypes.CUSTOM_NAME, result))
140+
.ifToRemove(() -> item.unsetComponent(ComponentTypes.CUSTOM_NAME));
141+
142+
return !translationResult.isUnchanged();
143+
}
144+
145+
private boolean translateLore(ItemStack item, Localized locale) {
146+
val loreOpt = item.getComponent(ComponentTypes.LORE);
147+
if (!loreOpt.isPresent()) {
148+
return false;
149+
}
150+
151+
val lore = loreOpt.get();
152+
AtomicBoolean loreChanged = new AtomicBoolean(false);
153+
List<Component> newLines = new ArrayList<>();
154+
for (Component line : lore.getLines()) {
155+
parser.translateComponent(
156+
line,
157+
locale,
158+
this.syntax
159+
)
160+
.map(ComponentUtils::splitByNewLine)
161+
.ifChanged(result -> {
162+
newLines.addAll(
163+
result.stream()
164+
.map(ComponentUtils::ensureNotItalic)
165+
.collect(Collectors.toList())
166+
);
167+
loreChanged.set(true);
168+
})
169+
.ifUnchanged(() -> newLines.add(line))
170+
.ifToRemove(() -> loreChanged.set(true));
171+
}
172+
if (!loreChanged.get()) {
173+
return false;
174+
}
175+
lore.setLines(newLines);
176+
return true;
177+
}
178+
179+
private boolean translateContainerContents(ItemStack item, Localized locale) {
180+
val containerContentsOpt = item.getComponent(ComponentTypes.CONTAINER);
181+
if (!containerContentsOpt.isPresent()) {
182+
return false;
183+
}
184+
185+
boolean contentsChanged = false;
186+
val containerContents = containerContentsOpt.get();
187+
for (ItemStack itemStack : containerContents.getItems()) {
188+
contentsChanged |= translateItem(itemStack, locale, false, false);
189+
}
190+
return contentsChanged;
191+
}
192+
193+
private boolean translateBook(ItemStack item, Localized locale) {
194+
val bookContentOpt = item.getComponent(ComponentTypes.WRITTEN_BOOK_CONTENT);
195+
if (!bookContentOpt.isPresent()) {
196+
return false;
197+
}
198+
199+
boolean contentsChanged = false;
200+
val bookContent = bookContentOpt.get();
201+
for (Iterator<Filterable<@NotNull Component>> it = bookContent.getPages().iterator(); it.hasNext(); ) {
202+
val page = it.next();
203+
val translationResult = parser.translateComponent(
204+
page.getRaw(),
205+
locale,
206+
syntax
207+
);
208+
translationResult
209+
.ifChanged(page::setRaw)
210+
.ifToRemove(it::remove);
211+
contentsChanged |= !translationResult.isUnchanged();
212+
}
213+
214+
return contentsChanged;
215+
}
216+
}

0 commit comments

Comments
 (0)