Skip to content

Commit

Permalink
Send clients with mod installed extra metadata for the custom info li…
Browse files Browse the repository at this point in the history
…nes included in the sent item stacks to allow for item stack syncing. Add new player filter feature for database querying
  • Loading branch information
ArkoSammy12 committed Aug 15, 2024
1 parent 75fce98 commit 804a389
Show file tree
Hide file tree
Showing 18 changed files with 309 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package xd.arkosammy.publicenderchest.mixin.client;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import xd.arkosammy.publicenderchest.PublicEnderChestKt;
import xd.arkosammy.publicenderchest.util.ducks.ItemStackDuck;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

@Mixin(ClientPlayNetworkHandler.class)
public abstract class ClientPlayNetworkHandlerMixin {

@WrapOperation(method = "onScreenHandlerSlotUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/ScreenHandlerSlotUpdateS2CPacket;getStack()Lnet/minecraft/item/ItemStack;"))
private ItemStack restoreOriginalItemStackAndSaveCustomInfo(ScreenHandlerSlotUpdateS2CPacket instance, Operation<ItemStack> original) {
ItemStack itemStack = original.call(instance);
LoreComponent loreComponent = itemStack.get(DataComponentTypes.LORE);
if (loreComponent == null) {
return itemStack;
}
String expectedMetadata = PublicEnderChestKt.formatInfoTextMetadata(instance.getSyncId(), instance.getRevision());
List<Text> originalLines = new ArrayList<>(loreComponent.lines());
List<Text> originalStyledLines = new ArrayList<>(loreComponent.styledLines());
ItemStack actualItemStack = itemStack.copy();
Predicate<Text> lineMetadataFilter = (line) -> {
boolean containsMetadata = line.getString().contains(expectedMetadata);
if (containsMetadata) {
Text customInfoLine = Text.literal(line.getString().replace(expectedMetadata, "")).formatted(Formatting.ITALIC, Formatting.DARK_PURPLE);
List<Text> currentCustomInfoLines = ((ItemStackDuck) (Object) actualItemStack).publicenderchest$getCustomInfoLines();
if (!currentCustomInfoLines.contains(customInfoLine)) {
((ItemStackDuck) (Object) actualItemStack).publicenderchest$addCustomInfoLine(customInfoLine);
}
return false;
} else {
return true;
}
};
List<Text> actualLines = originalLines.stream().filter(lineMetadataFilter).toList();
List<Text> actualStyledLines = originalStyledLines.stream().filter(lineMetadataFilter).toList();
LoreComponent actualLoreComponent = new LoreComponent(actualLines, actualStyledLines);
actualItemStack.set(DataComponentTypes.LORE, actualLoreComponent);
return actualItemStack;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package xd.arkosammy.publicenderchest.mixin.client;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import xd.arkosammy.publicenderchest.util.ducks.ItemStackDuck;

import java.util.ArrayList;
import java.util.List;

@Mixin(HandledScreen.class)
public abstract class HandledScreenMixin {

@ModifyReturnValue(method = "getTooltipFromItem", at = @At("RETURN"))
private List<Text> addCustomInfoLines(List<Text> original, ItemStack stack) {
List<Text> originalTooltipLines = new ArrayList<>(original);
List<Text> customInfoLines = ((ItemStackDuck) (Object) stack).publicenderchest$getCustomInfoLines();
originalTooltipLines.addAll(customInfoLines);
return originalTooltipLines;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package xd.arkosammy.publicenderchest

import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
import xd.arkosammy.publicenderchest.networking.C2SHandshakeResponsePayload
import xd.arkosammy.publicenderchest.networking.OpenPublicInventoryPayload
import xd.arkosammy.publicenderchest.networking.S2CHandshakeRequestPayload
import java.util.*

object PublicEnderChestClient : ClientModInitializer {

override fun onInitializeClient() {

ClientPlayNetworking.registerGlobalReceiver(S2CHandshakeRequestPayload.PACKET_ID) { payload, context ->
context.responseSender().sendPacket(C2SHandshakeResponsePayload(UUID.randomUUID()))
}
}

@JvmStatic
Expand Down
6 changes: 4 additions & 2 deletions src/client/resources/publicenderchest.client.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
"package": "xd.arkosammy.publicenderchest.mixin.client",
"compatibilityLevel": "JAVA_21",
"client": [
"ClientPlayerInteractionManagerMixin"
"ClientPlayerInteractionManagerMixin",
"ClientPlayNetworkHandlerMixin",
"HandledScreenMixin"
],
"injectors": {
"defaultRequire": 1
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import xd.arkosammy.publicenderchest.util.ducks.ItemStackDuck;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Mixin(ItemStack.class)
public class ItemStackMixin implements ItemStackDuck {
Expand All @@ -20,6 +22,9 @@ public class ItemStackMixin implements ItemStackDuck {
@Nullable
private LocalDateTime insertedTime;

@Unique
private final List<Text> customInfoLines = new ArrayList<>();

@Override
public void publicenderchest$setInserterName(Text name) {
this.inserterName = name;
Expand All @@ -40,4 +45,14 @@ public class ItemStackMixin implements ItemStackDuck {
return this.insertedTime;
}

@Override
public void publicenderchest$addCustomInfoLine(Text text) {
this.customInfoLines.add(text);
}

@Override
public List<Text> publicenderchest$getCustomInfoLines() {
return this.customInfoLines;
}

}
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
package xd.arkosammy.publicenderchest.mixin;

import com.google.common.collect.ImmutableList;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerSyncHandler;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import xd.arkosammy.publicenderchest.inventory.CustomGenericContainerScreenHandler;
import xd.arkosammy.publicenderchest.inventory.PublicInventory;
import xd.arkosammy.publicenderchest.inventory.PublicInventoryKt;
import xd.arkosammy.publicenderchest.util.CustomMutableText;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

@Mixin(ScreenHandler.class)
Expand All @@ -41,37 +29,4 @@ private boolean forceSlotUpdateForPublicInventory(boolean original, int slot, It
return false;
}

@WrapOperation(method = "checkSlotUpdates", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/ScreenHandlerSyncHandler;updateSlot(Lnet/minecraft/screen/ScreenHandler;ILnet/minecraft/item/ItemStack;)V"))
private void modifySentItemStack(ScreenHandlerSyncHandler instance, ScreenHandler screenHandler, int slot, ItemStack itemStack, Operation<Void> original) {
if (!(screenHandler instanceof CustomGenericContainerScreenHandler customScreenHandler)) {
original.call(instance, screenHandler, slot, itemStack);
return;
}
Inventory inventory = customScreenHandler.getInventory();
if (!(inventory instanceof PublicInventory publicInventory)) {
original.call(instance, screenHandler, slot, itemStack);
return;
}
List<CustomMutableText> customInfoLines = PublicInventoryKt.getCustomInfoLines(publicInventory.getStack(slot));
if (customInfoLines.isEmpty()) {
original.call(instance, screenHandler, slot, itemStack);
return;
}
LoreComponent loreComponent = itemStack.get(DataComponentTypes.LORE);
List<Text> newLines = new ArrayList<>();
if (loreComponent != null) {
newLines.addAll(loreComponent.lines());
}
newLines.addAll(customInfoLines);
LoreComponent newLoreComponent;
if (loreComponent != null) {
newLoreComponent = new LoreComponent(ImmutableList.copyOf(newLines), ImmutableList.copyOf(loreComponent.styledLines()));
} else {
newLoreComponent = new LoreComponent(ImmutableList.copyOf(newLines));
}
ItemStack sentItemStack = itemStack.copy();
sentItemStack.set(DataComponentTypes.LORE, newLoreComponent);
original.call(instance, screenHandler, slot, sentItemStack);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,23 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntity implements Se
@Unique
private int pageIndex = 0;

@Unique
private boolean hasMod = false;

public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile gameProfile) {
super(world, pos, yaw, gameProfile);
}

@Override
public void publicenderchest$setHasMod(boolean hasMod) {
this.hasMod = hasMod;
}

@Override
public boolean publicenderchest$hasMod() {
return this.hasMod;
}

@Override
public void publicenderchest$setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package xd.arkosammy.publicenderchest.mixin;

import com.google.common.collect.ImmutableList;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import xd.arkosammy.publicenderchest.PublicEnderChestKt;
import xd.arkosammy.publicenderchest.inventory.CustomGenericContainerScreenHandler;
import xd.arkosammy.publicenderchest.inventory.PublicInventory;
import xd.arkosammy.publicenderchest.inventory.PublicInventoryKt;
import xd.arkosammy.publicenderchest.util.CustomMutableText;
import xd.arkosammy.publicenderchest.util.ducks.ServerPlayerEntityDuck;

import java.util.ArrayList;
import java.util.List;

@Mixin(targets = "net.minecraft.server.network.ServerPlayerEntity$1")
public abstract class ServerPlayerEntitySyncHandlerMixin {

@Shadow @Final private ServerPlayerEntity field_29182;

@WrapOperation(method = "updateSlot", at = @At(value = "NEW", target = "net/minecraft/network/packet/s2c/play/ScreenHandlerSlotUpdateS2CPacket"))
private ScreenHandlerSlotUpdateS2CPacket modifySentItemStack(int syncId, int revision, int slot, ItemStack itemStack, Operation<ScreenHandlerSlotUpdateS2CPacket> original, ScreenHandler screenHandler) {
ServerPlayerEntity player = this.field_29182;
if (!(screenHandler instanceof CustomGenericContainerScreenHandler customScreenHandler)) {
return original.call(syncId, revision, slot, itemStack);
}
Inventory inventory = customScreenHandler.getInventory();
if (!(inventory instanceof PublicInventory publicInventory)) {
return original.call(syncId, revision, slot, itemStack);
}
List<CustomMutableText> customInfoLines = PublicInventoryKt.getCustomInfoLines(publicInventory.getStack(slot));
if (customInfoLines.isEmpty()) {
return original.call(syncId, revision, slot, itemStack);
}
if (((ServerPlayerEntityDuck) player).publicenderchest$hasMod()) {
for (CustomMutableText line : customInfoLines) {
line.getText().append(" " + PublicEnderChestKt.formatInfoTextMetadata(syncId, revision));
}
}
LoreComponent loreComponent = itemStack.get(DataComponentTypes.LORE);
List<Text> sentLines = new ArrayList<>();
if (loreComponent != null) {
sentLines.addAll(loreComponent.lines());
}
sentLines.addAll(customInfoLines);
LoreComponent sentLoreComponent;
if (loreComponent != null) {
sentLoreComponent = new LoreComponent(ImmutableList.copyOf(sentLines), ImmutableList.copyOf(loreComponent.styledLines()));
} else {
sentLoreComponent = new LoreComponent(ImmutableList.copyOf(sentLines));
}
ItemStack sentItemStack = itemStack.copy();
sentItemStack.set(DataComponentTypes.LORE, sentLoreComponent);
return original.call(syncId, revision, slot, sentItemStack);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.jetbrains.annotations.Nullable;

import java.time.LocalDateTime;
import java.util.List;

public interface ItemStackDuck {

Expand All @@ -17,4 +18,8 @@ public interface ItemStackDuck {
@Nullable
LocalDateTime publicenderchest$getInsertedTime();

void publicenderchest$addCustomInfoLine(Text text);

List<Text> publicenderchest$getCustomInfoLines();

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ public interface ServerPlayerEntityDuck {

void publicenderchest$showPage();

void publicenderchest$setHasMod(boolean hasMod);

boolean publicenderchest$hasMod();

}
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,8 @@ fun ItemStack.isEnderChest() : Boolean {
return false
}
return item.block is EnderChestBlock
}
}

@JvmStatic
fun formatInfoTextMetadata(syncId: Int, revision: Int) : String =
"publicenderchest:CustomText[syncId=$syncId, revision=$revision]"
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,32 @@ object DatabaseCommands {
}
.build()

val playerNameArgumentNode: ArgumentCommandNode<ServerCommandSource, String> = CommandManager
.argument("playerName", StringArgumentType.word())
.requires { src -> src.hasPermissionLevel(4) }
.suggests { context, builder ->
CommandSource.suggestMatching(
context.source.server.playerNames,
builder
)
}
.executes { ctx ->
val playerName: String = StringArgumentType.getString(ctx, "playerName")
val player: ServerPlayerEntity = ctx.source.playerOrThrow
val queryTypeName: String = StringArgumentType.getString(ctx, "timeQueryType")
val queryType: TimeQueryType = TimeQueryType.getFromCommandNodeName(queryTypeName) ?: return@executes Command.SINGLE_SUCCESS.also {
player.sendMessage(Text.literal("Time query type \"$queryTypeName\" does not exist!").formatted(Formatting.RED))
}
val days: Int = IntegerArgumentType.getInteger(ctx, "days")
val hours: Int = IntegerArgumentType.getInteger(ctx, "hours")
val minutes: Int = IntegerArgumentType.getInteger(ctx, "minutes")
val seconds: Int = IntegerArgumentType.getInteger(ctx, "seconds")
val queryContext = QueryContext(queryType, days, hours, minutes, seconds, playerName)
(player as ServerPlayerEntityDuck).`publicenderchest$showLogs`(queryContext)
Command.SINGLE_SUCCESS
}
.build()

rootNode.addChild(databaseNode)

databaseNode.addChild(purgeNode)
Expand All @@ -180,6 +206,8 @@ object DatabaseCommands {
queryWithHours.addChild(queryWithMinutes)
queryWithMinutes.addChild(queryWithSeconds)

queryWithSeconds.addChild(playerNameArgumentNode)

}

private fun sendMessageToPlayerOrConsole(player: ServerPlayerEntity?, text: MutableText, logType: LogType) {
Expand All @@ -190,7 +218,6 @@ object DatabaseCommands {
LogType.NORMAL -> PublicEnderChest.LOGGER.info(text.string)
LogType.WARNING -> PublicEnderChest.LOGGER.warn(text.string)
LogType.ERROR -> PublicEnderChest.LOGGER.error(text.string)

}
}
}
Expand Down
Loading

0 comments on commit 804a389

Please sign in to comment.