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
@@ -1,6 +1,7 @@
package com.rexcantor64.triton.packetinterceptor;

import com.github.retrooper.packetevents.event.PacketListener;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.event.UserDisconnectEvent;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
Expand All @@ -14,6 +15,7 @@
import com.rexcantor64.triton.packetinterceptor.handlers.DisconnectPacketHandler;
import com.rexcantor64.triton.packetinterceptor.handlers.EntityPacketHandler;
import com.rexcantor64.triton.packetinterceptor.handlers.GuiPacketHandler;
import com.rexcantor64.triton.packetinterceptor.handlers.ItemPacketHandler;
import com.rexcantor64.triton.packetinterceptor.handlers.ResourcePackPacketHandler;
import com.rexcantor64.triton.packetinterceptor.handlers.ScoreboardPacketHandler;
import com.rexcantor64.triton.packetinterceptor.handlers.TabPacketHandler;
Expand All @@ -39,7 +41,8 @@
*/
public class PacketEventsListener implements PacketListener {

private Map<PacketTypeCommon, BiConsumer<PacketSendEvent, TritonLanguagePlayer<?>>> receiveHandlers = Collections.emptyMap();
private Map<PacketTypeCommon, BiConsumer<PacketSendEvent, TritonLanguagePlayer<?>>> sendHandlers = Collections.emptyMap();
private Map<PacketTypeCommon, BiConsumer<PacketReceiveEvent, TritonLanguagePlayer<?>>> receiveHandlers = Collections.emptyMap();

/**
* Setup handlers according to what is enabled on config.
Expand All @@ -50,6 +53,7 @@ public void setupHandlers() {
val parser = Triton.get().getMessageParser();
val config = Triton.get().getConfig();
val updatedHandlers = new HashMap<PacketTypeCommon, BiConsumer<PacketSendEvent, TritonLanguagePlayer<?>>>();
val updatedReceiveHandlers = new HashMap<PacketTypeCommon, BiConsumer<PacketReceiveEvent, TritonLanguagePlayer<?>>>();

// parse allowed entity types from config
val allowedEntities = config.getAllowedEntityTypes().stream()
Expand Down Expand Up @@ -117,7 +121,7 @@ public void setupHandlers() {
updatedHandlers.put(PacketType.Play.Server.COMBAT_EVENT, deathScreenHandler::onCombatEventPacket);
updatedHandlers.put(PacketType.Play.Server.DEATH_COMBAT_EVENT, deathScreenHandler::onDeathCombatEventPacket);
}
if (config.isGuis()) {
if (config.isGuis() || config.isItems()) {
val guiHandler = new GuiPacketHandler(parser, config);
updatedHandlers.put(PacketType.Play.Server.OPEN_WINDOW, guiHandler::onOpenWindowPacket);
}
Expand All @@ -141,14 +145,35 @@ public void setupHandlers() {

updatedHandlers.put(PacketType.Play.Server.JOIN_GAME, entityHandler::onJoinGame);
}
if (config.isItems()) {
val itemHandler = new ItemPacketHandler(parser, config);
updatedHandlers.put(PacketType.Play.Server.SET_CURSOR_ITEM, itemHandler::onSetCursorItemPacket);
updatedHandlers.put(PacketType.Play.Server.SET_PLAYER_INVENTORY, itemHandler::onSetPlayerInventoryPacket);
updatedHandlers.put(PacketType.Play.Server.SET_SLOT, itemHandler::onSetSlotPacket);
updatedHandlers.put(PacketType.Play.Server.WINDOW_ITEMS, itemHandler::onWindowItemsPacket);
updatedHandlers.put(PacketType.Play.Server.CLOSE_WINDOW, itemHandler::onServerCloseWindowPacket);
updatedReceiveHandlers.put(PacketType.Play.Client.CLOSE_WINDOW, itemHandler::onClientCloseWindowPacket);
}

receiveHandlers = Collections.unmodifiableMap(updatedHandlers);
sendHandlers = Collections.unmodifiableMap(updatedHandlers);
receiveHandlers = Collections.unmodifiableMap(updatedReceiveHandlers);
}

@Override
public void onPacketSend(PacketSendEvent event) {
val type = event.getPacketType();

val handler = sendHandlers.get(type);
if (handler != null) {
val languagePlayer = Triton.get().getPlayerManager().get(event.getUser().getUUID());
handler.accept(event, languagePlayer);
}
}

@Override
public void onPacketReceive(PacketReceiveEvent event) {
val type = event.getPacketType();

val handler = receiveHandlers.get(type);
if (handler != null) {
val languagePlayer = Triton.get().getPlayerManager().get(event.getUser().getUUID());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,34 @@ public class GuiPacketHandler {

private final @NotNull MessageParser parser;
private final @NotNull MainConfig.FeatureSyntax syntax;
private final boolean translateGuiTitles;
private final boolean translateItems;

public GuiPacketHandler(@NotNull MessageParser parser, @NotNull MainConfig config) {
this.parser = parser;
this.syntax = config.getGuiSyntax();
this.translateGuiTitles = config.isGuis();
this.translateItems = config.isItems();
}

public void onOpenWindowPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
val packet = new WrapperPlayServerOpenWindow(event);

parser.translateComponent(
packet.getTitle(),
languagePlayer,
syntax
)
.getResultOrToRemove(Component::empty)
.ifPresent(result -> {
packet.setTitle(result);
event.markForReEncode(true);
});
if (this.translateItems) {
languagePlayer.getPacketEventsRefresh().setCurrentWindowId(packet.getContainerId());
}

if (translateGuiTitles) {
parser.translateComponent(
packet.getTitle(),
languagePlayer,
syntax
)
.getResultOrToRemove(Component::empty)
.ifPresent(result -> {
packet.setTitle(result);
event.markForReEncode(true);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.rexcantor64.triton.packetinterceptor.handlers;

import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetCursorItem;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPlayerInventory;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetSlot;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerWindowItems;
import com.rexcantor64.triton.config.MainConfig;
import com.rexcantor64.triton.language.parser.MessageParser;
import com.rexcantor64.triton.player.TritonLanguagePlayer;
import com.rexcantor64.triton.utils.ItemStackTranslationUtils;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.jetbrains.annotations.NotNull;

@RequiredArgsConstructor
public class ItemPacketHandler {

private final ItemStackTranslationUtils itemHandler;
private final boolean translateInventoryItems;

public ItemPacketHandler(@NotNull MessageParser parser, @NotNull MainConfig config) {
this.itemHandler = new ItemStackTranslationUtils(parser, config.getItemsSyntax());
this.translateInventoryItems = config.isInventoryItems();
}

public void onSetCursorItemPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
val packet = new WrapperPlayServerSetCursorItem(event);

if (!this.translateInventoryItems && languagePlayer.getPacketEventsRefresh().getCurrentWindowId() == 0) {
return;
}

val result = this.itemHandler.translateItem(packet.getStack(), languagePlayer);
if (result.isModified()) {
packet.setStack(result.getModified());
event.markForReEncode(true);
}
}

public void onSetPlayerInventoryPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
val packet = new WrapperPlayServerSetPlayerInventory(event);

if (!this.translateInventoryItems && languagePlayer.getPacketEventsRefresh().getCurrentWindowId() == 0) {
return;
}

val result = this.itemHandler.translateItem(packet.getStack(), languagePlayer);
if (result.isModified()) {
packet.setStack(result.getModified());
event.markForReEncode(true);
}
}

public void onSetSlotPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
val packet = new WrapperPlayServerSetSlot(event);

if (!this.translateInventoryItems && languagePlayer.getPacketEventsRefresh().getCurrentWindowId() == 0) {
return;
}

val result = this.itemHandler.translateItem(packet.getItem(), languagePlayer);
if (result.isModified()) {
packet.setItem(result.getModified());
event.markForReEncode(true);
}
}

public void onWindowItemsPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
val packet = new WrapperPlayServerWindowItems(event);

if (!this.translateInventoryItems && languagePlayer.getPacketEventsRefresh().getCurrentWindowId() == 0) {
return;
}

val carriedItem = packet.getCarriedItem();
if (carriedItem.isPresent()) {
val result = this.itemHandler.translateItem(carriedItem.get(), languagePlayer);
if (result.isModified()) {
packet.setCarriedItem(result.getModified());
event.markForReEncode(true);
}
}

val windowItems = packet.getItems();
for (int i = 0; i < windowItems.size(); i++) {
val item = windowItems.get(i);
val result = this.itemHandler.translateItem(item, languagePlayer);
if (result.isModified()) {
windowItems.set(i, result.getModified());
event.markForReEncode(true);
}
}
}

public void onClientCloseWindowPacket(@NotNull PacketReceiveEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
languagePlayer.getPacketEventsRefresh().setCurrentWindowId(0);
}

public void onServerCloseWindowPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
languagePlayer.getPacketEventsRefresh().setCurrentWindowId(0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.github.retrooper.packetevents.protocol.score.ScoreFormat;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientClickWindow;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBossBar;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook;
Expand All @@ -29,6 +30,7 @@
import com.rexcantor64.triton.Triton;
import com.rexcantor64.triton.config.MainConfig;
import com.rexcantor64.triton.language.parser.MessageParser;
import com.rexcantor64.triton.utils.ItemStackTranslationUtils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
Expand All @@ -39,6 +41,7 @@
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
Expand All @@ -60,6 +63,14 @@ public class PacketEventsRefresh {
private final Map<UUID, Player> tentativePlayerMap = new ConcurrentHashMap<>();
private final Map<Integer, Player> spawnedPlayerMap = new ConcurrentHashMap<>();

/**
* The window ID of the currently open window.
* If no window is open, this must be set to 0, which corresponds to the player's inventory.
*/
@Setter
@Getter
private int currentWindowId = 0;

private final TritonLanguagePlayer<?> languagePlayer;

/**
Expand Down Expand Up @@ -334,6 +345,10 @@ public void refreshAll() {
updatePlayerListHeaderFooter(user, syntax, parser);
updatePlayerList(user, syntax, parser);
}
if (cfg.isItems()) {
val handler = new ItemStackTranslationUtils(parser, cfg.getItemsSyntax());
updateInventoryItems(user, handler);
}
}

private void updateBossBars(@NotNull User user, @NotNull MainConfig.FeatureSyntax syntax, @NotNull MessageParser parser) {
Expand Down Expand Up @@ -644,6 +659,15 @@ private void updatePlayer(@NotNull User user, @NotNull MainConfig.FeatureSyntax
);
}

private void updateInventoryItems(@NotNull User user, @NotNull ItemStackTranslationUtils handler) {
if (user.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_17_1)) {
// Here we use a hack where we pretend to the server that the client is out-of-sync (i.e., incorrect stateId),
// making it resend the entire window contents
val packet = new WrapperPlayClientClickWindow(this.currentWindowId, -1, 0, Byte.MAX_VALUE, WrapperPlayClientClickWindow.WindowClickType.PICKUP, Collections.emptyMap(), Optional.empty());
user.receivePacketSilently(packet);
}
}

@RequiredArgsConstructor
@Getter
private static class ScoreboardObjective {
Expand Down
Loading